LockBits() выбрасывает "Недостаточно памяти" в параллельном Foreach?
Я новичок в C# и параллельной обработке. Я пытаюсь обработать кучу изображений, и я написал методы для обработки. И я добавил параллельный цикл foreach в список изображений, как показано ниже
Parallel.ForEach(Directory.GetFiles(path), new ParallelOptions { MaxDegreeOfParallelism = 2 }, fileName =>
{
List<string> tempList = new List<string>();
using (Bitmap imageBitmap= new Bitmap(fileName))
{
using (ImageProcessor imageProcessor= new ImageProcessor ())
{
tempList = imageProcessor.ProcessImage(imageBitmap);
}
}
if (tempList.Count != 0)
allElements.Add(tempList.FirstOrDefault());
});
В одном из методов, которые я использовал LockBits
способ получить BitMapData
изображения и копирование этих данных в byte[]
но метод вызывает исключение, код метода
private byte[] ImageToByteArray(Bitmap b, out int stride)
{
object sync = new object();
BitmapData bd;
lock (sync)
{
Rectangle rect = new Rectangle(0, 0, b.Width, b.Height);
bd = b.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);//This line throwing the exception.
try
{
byte[] pxl = new byte[bd.Stride * b.Height];
Marshal.Copy(bd.Scan0, pxl, 0, bd.Stride * b.Height);
stride = bd.Stride;
return pxl;
}
finally
{
b.UnlockBits(bd);
}
}
}
Я пытался lock
код, который использует LockBits
метод, так что одновременно только один поток использует код и, следовательно, память.
Я также пытался использовать lock
с вызовом методов из родительского метода, как
public List<string> ProcessImage(BitMap image)
{
object sync = new object();
int stride;
byte[] rawImg;
using (image)
{
lock (sync)
{
rawImg = ImageToByteArray(image, out stride);
}
processingImg = new ProcessImage(rawImg, image.Width, image.Height);
}
}
но все же исключение есть. Исключение не дает мне никакой трассировки стека или только объяснение. Исключение, которое я получаю, Out Of Memory
,
Я столкнулся с этим ответом, и когда я уменьшил MaximumDegreeOfParallelism
это сработало правильно.
В общем, я хотел знать,
1) почему код бросал Out Of Memory
исключение для более чем 2 потоков даже есть lock
по коду?
2) И возможно ли избежать этого исключения, если я увеличу DegreeOfParallelism
? Любая помощь будет отличной.
В случае любой путаницы не стесняйтесь комментировать.
1 ответ
Вопрос в том, насколько велики изображения, которые вы хотите обработать. Может быть, они просто слишком большие. Мой опыт также показывает, что вызов LockBits выделяет дополнительный объем памяти - фактически он удваивает объем выделенной памяти. Вы пытались обработать очень маленькую картинку?
Блокировка в вашем коде ничего не делает, потому что вы блокируете локальные переменные. Если вы хотите синхронизировать доступ к критическому разделу между потоками и хотите сделать это с блокировкой, вам нужно использовать объект, который используется всеми этими потоками. В вашем случае объект синхронизации должен быть объявлен как приватное поле класса ImageProcessor.
Я думаю, что увеличение DegreeOfParallelism не поможет или даже ухудшит ситуацию, потому что вашему коду потребуется больше памяти для обработки большего количества изображений.