У меня есть небольшое приложение-образец. Я работал над попыткой получить некоторые новые параллельные расширения .Net 4.0 (они очень приятные). Я сталкиваюсь с (возможно, очень глупой) проблемой с OutOfMemoryException. Мое главное приложение, которое я ищу, чтобы подключить этот образец к чтению некоторых данных и большого количества файлов, выполняет некоторую обработку на них, а затем записывает их где-то. Я столкнулся с некоторыми проблемами, когда файлы стали больше (возможно, GB) и были обеспокоены памятью, поэтому я хотел распараллелить то, что привело меня по этому пути.OutOfMemoryException в письме MemoryStream
Теперь приведенный ниже код получает OOME на небольших файлах, и я думаю, что я просто что-то пропустил. Он будет читать в 10-15 файлах и записывать их в parellel красиво, но затем он задыхается на следующем. Похоже, что он читается и пишет около 650 МБ. Будет оценен второй набор глаз.
Я читаю в MemorySteam из FileStream, потому что это то, что необходимо для основного приложения, и я просто пытаюсь воспроизвести это до некоторой степени. Он считывает данные и файлы со всех типов мест и работает с ними как с 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; }
}
}
Предварительная выделение MemoryStream решает мою проблему для всех, кроме самых больших файлов. Я буду разбивать большие файлы на куски. Просто не было этого в этом примере приложения. Благодарю. – MikeD