[英]MemoryStream - OutOfMemoryException when trying to allocate space
[英]OutOfMemoryException on MemoryStream writing
我有一個小樣本應用程序我正在努力嘗試獲得一些新的.Net 4.0 Parallel Extensions(它們非常好)。 我遇到了OutOfMemoryException的(可能真的很愚蠢)問題。 我的主要應用程序,我正在尋找插入此示例讀取一些數據和大量文件,對它們進行一些處理,然后將它們寫出來。 我遇到了一些問題,文件變得越來越大(可能是GB),並且擔心內存,所以我想並行化導致我走這條道路的事情。
現在,下面的代碼在較小的文件上得到OOME,我想我只是缺少一些東西。 它將讀入10-15個文件並很好地將它們寫在parellel中,但隨后它會在下一個文件中窒息。 看起來它的讀寫速度約為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中的空循環是文字,那么你正在燒掉不必要的CPU周期。 最好更好地使用solTask.Wait()。
但是,如果單個文件可以以GB為單位運行,那么仍然存在至少在內存中保留1個的問題,通常為2(1個正在讀取,1個正在處理/寫入。
PS1:我剛剛意識到你沒有預先分配MemStream。 這很糟糕,它必須經常為一個大文件重新調整大小,這會花費大量內存。 更好地使用以下內容:
var ms = new MemoryStream(fs.Length);
然后,對於大文件,您必須考慮大對象堆(LOH)。 您確定無法分段處理文件並處理它們嗎?
PS2:你不需要構造函數參數的ref,但這不是問題。
只需快速查看,即可獲得ServiceStage.Execute方法
var ms = new MemoryStream();
我沒有看到你在哪里關閉ms或在使用中。 你確實在其他課程中使用。 這是一回事。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.