2013-12-20 82 views
1

我正在通過USB設備下載視頻文件。該程序將文件存儲在byte[]陣列中,然後使用WriteAllBytes寫入新文件。但完成後,即使在將null指定爲byte[]後,系統內存仍然在使用中。C#在使用字節[]後清除系統內存變量

下面是代碼:

byte[] myByte = session.DownloadFile(InFile); 
File.WriteAllBytes(OutFile, myByte); 
myByte = null; 

session.DownloadFile()是我自己的類這一切工作正常只是一個記憶的問題。如果程序使用的內存超過1GB,則程序崩潰。

+3

「使用中」是GC系統中的灰色區域。看看TaskManager在這裏不是一個好的診斷。只要你沒有得到OOM例外:沒問題。 –

+2

這不是處理大文件的好方法,如果是4gb呢?如果可能的話,IMO會更好地使用流,並以塊爲單位寫入目標文件。 – Gavin

+0

看看這個(即不要使用那麼多的內存,如果可能的話)http://stackoverflow.com/questions/2269607/how-to-programmatically-download-a-large-file-in-c-sharp檢查接受回答。 – Gavin

回答

1

而不是嘗試在內存集合或嘗試釋放內存的GC上進行存儲。您應該使用流而不是大數據字節數組。這是什麼流是建立。

如果您的應用程序爲.NET 4.5,您可以在流大小上使用CopyTo方法。否則,您可以手動編寫分塊代碼。您可以在How to use Stream.CopyTo on .NET Framework 3.5?

一個例子,你應該嘗試做這樣的事情:

int blockSize = 8192; // The size of the array used to chunk, default is 4096 

using(var fileStream = File.Open("C:\\path\\to\\destination.file") 
using(var usbStream = session.OpenFileStream(InFile)) { 
    usbStream.CopyTo(fileStream, blockSize); 
} 

這樣,你的應用程序將使用blockSize(以字節爲單位)來複制數據,而不會更多。

這將需要您上面示例中的session對象支持流式傳輸I/O。否則,如果您編寫了session類,請將其重新設置爲通過返回Stream而不是byte[]來支持流式傳輸。

您不必擔心您正在複製的文件大小會導致程序崩潰。您將能夠支持底層文件系統支持的任何內容。

+0

歧視和點答案,但我用來下載文件的第三方庫不支持流 –

0

如果您在32位模式下運行,那麼您的進程將有2個  GB可用內存(其他2   GB爲系統保留)。但是,根據我的經驗,大多數32位C#應用程序往往會在1.5   GB標記周圍內存不足。

如果你保存的內存塊大於85   KB,那麼這些將進入large object heap。直到最近,這還沒有被壓縮,所以可能有足夠的空閒內存,但是沒有一個範圍足以滿足大型對象的單個請求。在這種情況下,您將耗盡內存。

如果你正在下載的文件很大,那麼我建議你將它下載到一個大塊文件中,然後寫出一個臨時文件。當你完成下載時,所有的塊將文件重命名爲你想要的實際文件。這將減少應用程序中的內存需求,但需要更多的工作。

1

只要內存結構不再使用,它​​就被標記爲由CLR刪除。 CLR將決定何時釋放內存。

你可以明確地將該值設置爲空,或者你可以把使用變量在它自己的代碼塊,像這樣:

{ 
    byte[] myByte = ... 
    File.WriteAllBytes(....); 
} 

是塊內聲明被標記爲刪除的任何變量在退出該塊時。

但是,要重複一遍:CLR會決定內存何時被釋放,並且在可能和必要時會這樣做。在.NET Framework 4.5.1中,大型對象堆在必要時也會被壓縮。

所以,如果遇到內存問題,它可能不是由於字節數組未被清理......可能您正在下載的視頻文件非常大,或者功能可能需要太多的內存。