2013-12-20 36 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中,大型对象堆在必要时也会被压缩。

所以,如果遇到内存问题,它可能不是由于字节数组未被清理......可能您正在下载的视频文件非常大,或者功能可能需要太多的内存。