我正在通过USB设备下载视频文件。该程序将文件存储在byte[]
数组中,然后使用WriteAllBytes
写入新文件。但在完成后,即使我将null
分配给byte[]
,系统内存仍在使用。
以下是代码:
byte[] myByte = session.DownloadFile(InFile);
File.WriteAllBytes(OutFile, myByte);
myByte = null;
session.DownloadFile()
是我自己的类,它只是一个内存问题。如果程序使用的内存超过1GB,程序将崩溃。
答案 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。直到最近,这从未被压缩过,因此可以有足够的可用内存,但不能有足够大的范围来满足大型对象的单个请求。在这种情况下,你将耗尽内存。
如果您下载的文件很大,我建议您将其下载并以块的形式写入临时文件。当您下载完所有块后,首先将文件重命名为您想要的实际文件。这将减少应用程序中的内存需求,但需要更多的工作。