В настоящее время я отлаживаю метод, который мы используем для тегов изображений с определенным текстом перед их отображением в нашей системе.
Метод тега выглядит следующим образом:
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;
}
Вставить вещи в контекст: этот метод вызывается после того, как изображение было извлечено с нашего сервера изображений и сохранено в локальном кеше (что наша система использует совместно с другими системами, для которых нужны одни и те же изображения).
У нас были проблемы с OutOfMemoryExceptions
при достижении using (Graphics...
(когда изображение должно быть извлечено с сервера до отметки, если изображение существует в кеше, тегирование не было проблемой).
Чтобы предотвратить/обойти исключение OutOfMemoryException, я пробовал три разных подхода, и, хотя они работают, мне действительно не нравится ни одна из них.
Сначала я попытался сделать общий GC.Collect();
перед вызовом Graphics.FromImage(image)
, который работал (конечно), но мне не нравится принудительно собирать, так как он сильно ударил по производительности.
Мой второй подход заключался в вызове GC.Collect()
в catch-statement, а затем рекурсивном вызове TagAsProductImage(image)
, но это может привести к бесконечному циклу, если GC не освободит достаточное количество памяти.
И, наконец, я закончил с приведенным выше кодом, и я не могу сказать, что я тоже люблю.
Возможно, мне удастся использовать GC.Collect()
, поскольку вся работа по получению изображения из тега обслуживания → сохранение → довольно велика, поэтому производительность, получаемая от сбора, будет минимальной, но я бы действительно как лучшее решение.
Если у кого-то есть разумное решение, делитесь им.