gpt4 book ai didi

c# - MemoryStream 写入时出现 OutOfMemoryException

转载 作者:行者123 更新时间:2023-11-30 15:49:18 25 4
gpt4 key购买 nike

我有一个小示例应用程序,我正在尝试让一些新的 .Net 4.0 并行扩展运行(它们非常好)。我遇到了一个(可能真的很愚蠢)OutOfMemoryException 问题。我希望将此示例插入的主要应用程序读取一些数据和大量文件,对它们进行一些处理,然后将它们写到某个地方。我遇到了一些文件变大(可能是 GB)的问题,并且担心内存,所以我想并行化导致我走上这条路的事情。

现在下面的代码在较小的文件上得到了 OOME,我想我只是遗漏了一些东西。它将读入 10-15 个文件并很好地并行写出它们,但随后它会在下一个文件中阻塞。看起来它的读写大约有650MB。我们将不胜感激。

我正在从 FileStream 读入 MemorySteam,因为这是主应用程序所需要的,我只是想在某种程度上复制它。它从各种类型的位置读取数据和文件,并将它们作为 MemoryStreams 处理。

这是使用 .Net 4.0 Beta 2,VS 2010。

namespace ParellelJob
{
class Program
{
BlockingCollection<FileHolder> serviceToSolutionShare;
static void Main(string[] args)
{
Program p = new Program();
p.serviceToSolutionShare = new BlockingCollection<FileHolder>();
ServiceStage svc = new ServiceStage(ref p.serviceToSolutionShare);
SolutionStage sol = new SolutionStage(ref p.serviceToSolutionShare);

var svcTask = Task.Factory.StartNew(() => svc.Execute());
var solTask = Task.Factory.StartNew(() => sol.Execute());

while (!solTask.IsCompleted)
{

}

}
}

class ServiceStage
{
BlockingCollection<FileHolder> outputCollection;
public ServiceStage(ref BlockingCollection<FileHolder> output)
{
outputCollection = output;
}

public void Execute()
{
var di = new DirectoryInfo(@"C:\temp\testfiles");
var files = di.GetFiles();
foreach (FileInfo fi in files)
{
using (var fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read))
{
int b;
var ms = new MemoryStream();
while ((b = fs.ReadByte()) != -1)
{
ms.WriteByte((byte)b); //OutOfMemoryException Occurs Here
}
var f = new FileHolder();
f.filename = fi.Name;
f.contents = ms;

outputCollection.TryAdd(f);
}
}
outputCollection.CompleteAdding();

}
}

class SolutionStage
{
BlockingCollection<FileHolder> inputCollection;
public SolutionStage(ref BlockingCollection<FileHolder> input)
{
inputCollection = input;
}
public void Execute()
{
FileHolder current;
while (!inputCollection.IsCompleted)
{
if (inputCollection.TryTake(out current))
{
using (var fs = new FileStream(String.Format(@"c:\temp\parellel\{0}", current.filename), FileMode.OpenOrCreate, FileAccess.Write))
{
using (MemoryStream ms = (MemoryStream)current.contents)
{
ms.WriteTo(fs);
current.contents.Close();
}
}
}
}
}
}

class FileHolder
{
public string filename { get; set; }
public Stream contents { get; set; }
}
}

最佳答案

主要逻辑似乎没问题,但如果 main 中的空 while 循环是字面意思,那么您正在消耗不必要的 CPU 周期。最好改用 solTask​​.Wait()。

但如果单个文件可以以千兆字节运行,您仍然会遇到至少 1 个完全保存在内存中的问题,通常是 2 个(1 个正在读取,1 个正在处理/写入。

PS1:我刚刚意识到您没有预先分配 MemStream。这很糟糕,对于一个大文件,它必须经常调整大小,这会消耗大量内存。最好使用类似的东西:

var ms = new MemoryStream(fs.Length);

然后,对于大文件,您必须考虑大对象堆 (LOH)。您确定不能将文件分成几段并进行处理吗?

PS2:你不需要构造函数参数上的引用,但这不是问题所在。

关于c# - MemoryStream 写入时出现 OutOfMemoryException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1767096/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com