C # Bitmap - Cannot find how to remove OutOfMemoryException

If I execute the code below, an OutOfMemoryException occurs either in the line

 using (Bitmap bitmap1 = new Bitmap(FrameToFilePath(interval.Start - 1))) 

or string

 using (Bitmap bitmap2 = new Bitmap(FrameToFilePath(interval.End + 1))) 

when the inner statement to execute is executed approximately 1000 times.

However, I do not know why an OutOfMemoryException occurs. I seem to have written enough using to host Bitmap objects. Where is a memory leak?

 class Program { static void Main(string[] args) { // Some code to initialize List<Interval> intervals Parallel.ForEach(intervals, interval => { using (Bitmap bitmap1 = new Bitmap(FrameToFilePath(interval.Start - 1))) using (Bitmap bitmap2 = new Bitmap(FrameToFilePath(interval.End + 1))) { for (int i = interval.Start; i <= interval.End; i++) { ColorMatrix colorMatrix = new ColorMatrix(); // Identity matrix colorMatrix.Matrix33 = (i - interval.Start + 1F) / (interval.Span + 1F); // Alpha using (ImageAttributes imageAttributes = new ImageAttributes()) using (Bitmap intermediate = new Bitmap(bitmap1.Width, bitmap1.Height, PixelFormat.Format32bppArgb)) using (Graphics graphics = Graphics.FromImage(intermediate)) { imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; graphics.DrawImage(bitmap1, 0, 0); graphics.DrawImage(bitmap2, new Rectangle(0, 0, intermediate.Width, intermediate.Height), 0, 0, bitmap2.Width, bitmap2.Height, GraphicsUnit.Pixel, imageAttributes); intermediate.Save(FrameToFilePath(i), ImageFormat.Png); } } } }); } static string FrameToFilePath(int frame) { return string.Format(@"C:\(some path)\frames\frame-{0:00000}.png", frame); } } class Interval { public int Start { get; set; } public int End { get; set; } public int Span { get { return End - Start + 1; } } } 

EDIT : OK. Maybe because Parallel.ForEach starts tasks before other tasks finish, so more and more tasks start, but Bitmap were not GCed, because the tasks were not completed. Well, if so, how can I fix this to avoid an OutofMemoryException? I'm not sure if that is the case though ...

+5
source share
1 answer

I came across something similar (but not similar enough for me to mark this as a duplicate) for myself . What you can do is set ParallelOptions.MaximumDegreeOfParallelism so as not to create additional tasks if it sees that the work is stalled.

 Parallel.ForEach(intervals, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, (interval) => { //... }); 

The reason you get this problem is because you are not connected to the CPU, but to the IO of the disk while reading the file returned from FrameToFilePath . This results in a low CPU% and Parallel.ForEach detects a low%, and tries to cause more tasks to bring the usage to 100%. Setting max parallelism means that it stops trying to reach 100% as soon as a certain number of tasks are specified. You can use a number larger than Environment.ProcessorCount , but the main bottleneck is your IO file.

+6
source

Source: https://habr.com/ru/post/1210361/


All Articles