使用byte []变量后C#清除系统内存

时间:2013-12-20 10:53:59

标签: c# memory download system libusb

我正在通过USB设备下载视频文件。该程序将文件存储在byte[]数组中,然后使用WriteAllBytes写入新文件。但在完成后,即使我将null分配给byte[],系统内存仍在使用。

以下是代码:

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

session.DownloadFile()是我自己的类,它只是一个内存问题。如果程序使用的内存超过1GB,程序将崩溃。

3 个答案:

答案 0 :(得分:1)

只要不再使用内存结构,CLR就会将其标记为删除。 CLR将决定何时释放内存。

您可以将值显式设置为null,或者您可以将使用该变量的代码放在其自己的块中,如下所示:

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

在退出块时,块中声明的任何变量都会被标记为删除。

但是,重复一遍:CLR决定内存实际释放的时间,并在可能和必要时执行。在.NET Framework 4.5.1中,大对象堆也会在必要时进行压缩。

因此,如果您遇到内存问题,可能不是因为字节数组没有被清理......可能您正在下载的视频文件非常大,或者WriteAllBytes函数可能也需要很多记忆。

答案 1 :(得分:1)

而不是尝试存储内存或GC尝试释放内存。您应该使用流而不是大字节数据数组。这就是为其构建的流。

如果您的应用是CopyTo 4.5,则可以在流大小上使用.NET方法。否则,您可以手动编写分块代码。您可以在 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[]来重新支持流式传输。

您永远不必担心复制文件的大小会导致程序崩溃。您将能够支持任何底层文件系统支持。

答案 2 :(得分:0)

如果您在32位模式下运行,那么您的进程将有2 GB可用内存(另外2 GB是为系统保留的)。但是,根据我的经验,大多数32位C#应用程序的内存大概都在1.5 GB左右。

如果你持有大于85 KB的内存块,那么这些将进入large object heap。直到最近,这从未被压缩过,因此可以有足够的可用内存,但不能有足够大的范围来满足大型对象的单个请求。在这种情况下,你将耗尽内存。

如果您下载的文件很大,我建议您将其下载并以块的形式写入临时文件。当您下载完所有块后,首先将文件重命名为您想要的实际文件。这将减少应用程序中的内存需求,但需要更多的工作。