【发布时间】:2010-11-11 13:03:05
【问题描述】:
我目前正在调试一种方法,用于在将图像显示在系统中之前用特定文本标记图像。
标签方法现在是这样的:
private static Image TagAsProductImage(Image image)
{
try
{
// Prepares the garbage collector for added memory pressure (500000 bytes is roughly 485 kilobytes).
// Should solve some OutOfMemoryExceptions.
GC.AddMemoryPressure(500000);
using (Graphics graphics = Graphics.FromImage(image))
{
// Create font.
Font drawFont = new Font("Tahoma", image.Width*IMAGE_TAG_SIZE_FACTOR);
// Create brush.
SolidBrush drawBrush = new SolidBrush(Color.Black);
// Create rectangle for drawing.
RectangleF drawRect = new RectangleF(0, image.Height - drawFont.GetHeight(), image.Width,
drawFont.GetHeight());
// Set format of string to be right-aligned.
StringFormat drawFormat = new StringFormat();
drawFormat.Alignment = StringAlignment.Far;
// Draw string to screen.
graphics.DrawString(TAG_TEXT, drawFont, drawBrush, drawRect, drawFormat);
}
}
// If an out of memory exception is thrown, return the unaltered image.
catch(OutOfMemoryException)
{
GC.RemoveMemoryPressure(500000);
return image;
}
GC.RemoveMemoryPressure(500000);
return image;
}
在上下文中:在从我们的图像服务器检索图像并保存到本地缓存(我们的系统与需要相同图片的其他系统共享)之后调用此方法。
我们在到达using (Graphics... 时遇到了OutOfMemoryExceptions 的问题(当需要在标记之前从服务器检索图像时,如果图像存在于缓存中,则标记没有问题)。
为了防止/规避 OutOfMemoryException,我尝试了三种不同的方法,虽然它们有效,但我并不喜欢其中任何一种。
首先,我尝试在调用 Graphics.FromImage(image) 之前执行通用的 GC.Collect(); (当然),但我不喜欢强制收集,因为它会对性能造成很大影响。
我的第二种方法是在 catch 语句中调用 GC.Collect(),然后递归调用 TagAsProductImage(image),但如果 GC 无法释放足够的内存,这可能会导致无限循环。
最后我得到了上面的代码,我不能说我很喜欢。
我可能可以不使用GC.Collect(),因为从服务获取图像 -> 保存 -> 标记的整个操作非常大,因此收集的性能影响很小,但我真的喜欢更好的解决方案。
如果有人对此有聪明的解决方案,请分享。
【问题讨论】:
标签: c# garbage-collection out-of-memory