Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# FileStream.Write()抛出OutOfMemoryException的可能原因?_C#_.net_Garbage Collection_Filestream_Out Of Memory - Fatal编程技术网

C# FileStream.Write()抛出OutOfMemoryException的可能原因?

C# FileStream.Write()抛出OutOfMemoryException的可能原因?,c#,.net,garbage-collection,filestream,out-of-memory,C#,.net,Garbage Collection,Filestream,Out Of Memory,我有10个线程将数千个小缓冲区(每个16-30字节)随机写入一个大文件。某些线程在FileStream.Write()操作上抛出OutOfMemoryException 是什么导致OutOfMemoryException?找什么 我使用的文件流是这样的(对于每一个编写的项目,这段代码都从10个不同的线程运行): 我怀疑FileStream中分配的所有缓冲区没有被GC及时释放。我不明白的是,为什么CLR不是抛出,而是运行GC循环并释放所有未使用的缓冲区?缓冲区通常不会在文件流中分配。也许问题在于“

我有10个线程将数千个小缓冲区(每个16-30字节)随机写入一个大文件。某些线程在FileStream.Write()操作上抛出OutOfMemoryException

是什么导致OutOfMemoryException?找什么

我使用的文件流是这样的(对于每一个编写的项目,这段代码都从10个不同的线程运行):


我怀疑FileStream中分配的所有缓冲区没有被GC及时释放。我不明白的是,为什么CLR不是抛出,而是运行GC循环并释放所有未使用的缓冲区?

缓冲区通常不会在文件流中分配。也许问题在于“写入数千个小缓冲区”这一行——你真的是这个意思吗?通常会多次重复使用缓冲区(即在不同的读/写调用上)


还有-这是一个单独的文件吗?单个文件流不能保证线程安全。。。因此,如果您不进行同步,则可能会出现混乱。

这些限制可能来自底层操作系统,而.NET Framework无法克服这些限制

从您的代码示例中,我无法推断您是同时打开了大量这些FileStream对象,还是按顺序快速打开它们。使用“using”关键字将确保在fs.Write()调用后关闭文件。关闭文件不需要GC循环

FileStream类实际上是面向文件的顺序读/写访问的。如果您需要快速写入大文件中的随机位置,您可能需要考虑使用虚拟文件映射

更新:在4.0之前,.NET似乎不会正式支持虚拟文件映射。您可能想看看此功能的第三方实现


Dave

如果代码显示有十个线程正在打开文件,那么一次最多可以有十个未经分解的FileStream对象。是的,FileStream有内部缓冲区,其大小在代码中用“BigBufferSizeInBytes”指定。你能透露一下确切的价值吗?如果这个容量足够大(例如约100MB),则很可能是问题的根源

默认情况下(即,在构造时不指定数字),此缓冲区为4kB,对于大多数应用程序来说,这通常是合适的。一般来说,如果您真的关心磁盘写入性能,那么您可能会将其增加到100kB,但不会超过100kB

但是,对于您的特定应用程序来说,这样做没有多大意义,因为所说的缓冲区包含的字节数永远不会超过您在处理FileStream对象之前写入的16-30字节


为了回答您的问题,只有在GC运行后无法分配请求的内存时才会抛出OutOfMemoryException。同样,如果缓冲区真的很大,那么系统可能会有足够的内存,而不是连续的块。这是因为大型对象堆从未被压缩。

我已经多次提醒过人们这一点,但当您似乎拥有大量可用内存或应用程序运行正常时,可以相当巧妙地抛出该异常

我经常遇到这个问题,因为我几乎完全按照你在这里的描述来做

您需要发布更多代码才能正确回答此问题。然而,我猜这也可能与潜在的万圣节问题有关

您正在读取的缓冲区也可能是问题所在(同样与大型对象堆相关)。同样,您需要提供更多关于循环中发生了什么的详细信息。我刚刚解决了我遇到的最后一个bug,它实际上是相同的(我正在执行许多并行哈希更新,这些更新都要求在输入文件的读操作中保持独立的状态)

哎呀!刚刚翻过屏幕,注意到“BigBufferSizeInBytes”,我再次倾向于大对象堆


如果我是你,(由于缺乏上下文,这非常困难),我会提供一个小的分派“mbuf”,在这里你可以复制进和复制出,而不是允许所有的分散线程在你的大备份阵列中单独读取。。。(也就是说,很难不使用非常微妙的文件代码语法来进行不必要的分配)。

我也经历过类似的情况,我想知道您是否已经找到了问题的根源

我的代码在文件之间进行了大量复制,在不同的字节文件之间传递了相当多的MEG。我注意到,虽然进程内存使用保持在一个合理的范围内,但在复制过程中,系统内存分配急剧上升,超出了进程的使用量

我已经跟踪到了FileStream.Write()调用的问题——当这一行被取出时,内存使用情况似乎和预期的一样。我的BigBufferSizeInBytes是默认值(4k),我看不到任何地方可以收集这些数据


如果您在查看问题时发现任何问题,我们将不胜感激

我现在不是在寻找最佳设计,我只是想知道为什么我会得到OutOfMemoryExceptions。是的,我有许多小的缓冲区,它们不能被重用(这是在集成测试的上下文中)。我为每个这样的缓冲区分配一个FileStream,因此没有线程问题。缓冲区大小是1mb——不足以消耗内存。好的,在这种情况下,我建议您发布一个最小但完整的程序,显示您描述的行为。我知道这可能需要做很多工作,但目前我看不到任何内在的原因,为什么你的代码会有内存问题。有一件事可以很好地解释您所看到的效果,那就是当FileStream对象由于某种原因无法进行GCD时:您是否添加了FileStream对象
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite, BigBufferSizeInBytes, FileOptions.SequentialScan))
{
 ...
 fs.Write();
}