C# 位图 - 找不到如何删除 OutOfMemoryException
C# Bitmap - Cannot find how to remove OutOfMemoryException
如果我执行下面的代码,OutOfMemoryException
出现在行
using (Bitmap bitmap1 = new Bitmap(FrameToFilePath(interval.Start - 1)))
或行
using (Bitmap bitmap2 = new Bitmap(FrameToFilePath(interval.End + 1)))
当内部for语句执行了大约1000次时。
但是,我不知道为什么会出现OutOfMemoryException。我想我已经写了足够 using
来处理 Bitmap
个对象。内存泄漏发生在哪里?
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; } }
}
编辑:好的。可能是因为 Parallel.ForEach
在其他任务结束之前生成了任务,所以越来越多的任务开始了,但是 Bitmap
s 没有因为任务没有结束而被 GC。那么,如果是这种情况,如何解决它以避免 OutofMemoryException?我不确定是否是这种情况...
我 运行 进入一个相似的(但不够相似,我不想将其标记为重复)issue myself。您可以做的是将 ParallelOptions.MaximumDegreeOfParallelism
设置为在发现工作停滞时不创建额外的任务。
Parallel.ForEach(intervals,
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
(interval) =>
{
//...
});
您遇到此问题的原因是您所绑定的不是 CPU,而是在读取从 FrameToFilePath
返回的文件期间驱动器的 IO。这会导致 CPU % 较低,并且 Parallel.ForEach
检测到该低 % 并尝试生成更多任务以使使用率达到 100%。设置最大并行度会告诉它在创建一定数量的任务后停止尝试达到 100%。您可以使用大于 Environment.ProcessorCount
的数字,但您的主要瓶颈是您的文件 IO。
如果我执行下面的代码,OutOfMemoryException
出现在行
using (Bitmap bitmap1 = new Bitmap(FrameToFilePath(interval.Start - 1)))
或行
using (Bitmap bitmap2 = new Bitmap(FrameToFilePath(interval.End + 1)))
当内部for语句执行了大约1000次时。
但是,我不知道为什么会出现OutOfMemoryException。我想我已经写了足够 using
来处理 Bitmap
个对象。内存泄漏发生在哪里?
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; } }
}
编辑:好的。可能是因为 Parallel.ForEach
在其他任务结束之前生成了任务,所以越来越多的任务开始了,但是 Bitmap
s 没有因为任务没有结束而被 GC。那么,如果是这种情况,如何解决它以避免 OutofMemoryException?我不确定是否是这种情况...
我 运行 进入一个相似的(但不够相似,我不想将其标记为重复)issue myself。您可以做的是将 ParallelOptions.MaximumDegreeOfParallelism
设置为在发现工作停滞时不创建额外的任务。
Parallel.ForEach(intervals,
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
(interval) =>
{
//...
});
您遇到此问题的原因是您所绑定的不是 CPU,而是在读取从 FrameToFilePath
返回的文件期间驱动器的 IO。这会导致 CPU % 较低,并且 Parallel.ForEach
检测到该低 % 并尝试生成更多任务以使使用率达到 100%。设置最大并行度会告诉它在创建一定数量的任务后停止尝试达到 100%。您可以使用大于 Environment.ProcessorCount
的数字,但您的主要瓶颈是您的文件 IO。