Предотвращение OutOfMemoryException с помощью GC.AddMemoryPressure ()?

В настоящее время я отлаживаю метод, который мы используем для пометки изображений определенным текстом перед их отображением в нашей системе.

Метод тега в настоящий момент выглядит так:

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;
}

Чтобы поместить вещи в контекст: этот метод вызывается после того, как изображение было получено с нашего сервера изображений и сохранено в локальном кеше (который наша система использует совместно с другими системами, которым нужны те же изображения ).

Мы ' Collect () в операторе catch, а затем рекурсивно вызывает TagAsProductImage (image) , но это может привести к бесконечному циклу, если сборщик мусора не сможет освободить достаточно памяти.

И, наконец, я закончил вверх с приведенным выше кодом, который я не могу сказать, что мне нравится ни то, ни другое.

Мне, вероятно, удастся избежать использования GC.Collect () , поскольку вся операция получения изображения из услуга -> сохранение -> теги - довольно большая проблема, поэтому снижение производительности от сбора будет минимальным, но я бы действительно хотел лучшее решение.

Если у кого-то есть умное решение, поделитесь.

16
задан Sam 7 July 2014 в 10:38
поделиться