С# исключение нехватки памяти в GetThumbnailImage на сервере

Я запускаю приведенный ниже код для создания миниатюры, когда пользователь отправляет нам изображение:

public int AddThumbnail(byte[] originalImage, File parentFile)
    {
        File tnFile = null;
        try
        {
            System.Drawing.Image image;
            using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(originalImage))
            {
                image = System.Drawing.Image.FromStream(memoryStream);
            }
            Log.Write("Original image width of [" + image.Width.ToString() + "] and height of [" + image.Height.ToString() + "]");
            //dimensions need to be changeable
            double factor = (double)m_thumbnailWidth / (double)image.Width;

            int thHeight = (int)(image.Height * factor);
            byte[] tnData = null;
            Log.Write("Thumbnail width of [" + m_thumbnailWidth.ToString() + "] and height of [" + thHeight + "]");
            using (System.Drawing.Image thumbnail = image.GetThumbnailImage(m_thumbnailWidth, thHeight, () => false, IntPtr.Zero))
            {                    
                using (System.IO.MemoryStream tnStream = new System.IO.MemoryStream())
                {
                    thumbnail.Save(tnStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                    tnData = new byte[tnStream.Length];
                    tnStream.Position = 0;
                    tnStream.Read(tnData, 0, (int)tnStream.Length);
                }
            }
//there is other code here that is not relevant to the problem

        }
        catch (Exception ex)
        {
            Log.Error(ex);
        }

        return (tnFile == null ? -1 : tnFile.Id);
    }

Это отлично работает на моей машине, но когда я запускаю его на тестовом сервере, я всегда получаю исключение из памяти в строке: using (System.Drawing.Image thumbnail = image.GetThumbnailImage(m_thumbnailWidth, thHeight, () => false , IntPtr.Zero)) Он не манипулирует большим изображением: он пытается преобразовать изображение 480 * 640 в миниатюру 96 * 128. Я не знаю, как исследовать/решить эту проблему. У кого-нибудь есть предложения? Это всегда происходит, даже после перезапуска IIS. Сначала я подумал, что изображение может быть повреждено, но размеры правильные. Спасибо.


person David Christopher Reynolds    schedule 17.12.2014    source источник
comment
У вас просто не хватает памяти на сервере? Получите монитор производительности, отслеживайте размеры кучи, генераторы сборщика мусора, общее потребление памяти.   -  person    schedule 17.12.2014
comment
Просто дикая догадка, возможно, ваша машина имеет 64-битную архитектуру, а сервер — 32-битную, что означает, что на вашей машине доступно гораздо больше памяти.   -  person barca_d    schedule 17.12.2014
comment
GDI печально известен выбрасыванием OOM, даже если память не является проблемой. GDI часто возвращает ошибку при выделении памяти практически при любой ошибке, которую библиотека .NET переводит в OOM, даже если выделение не удалось по какой-либо другой причине. Возможно это серьезная проблема с памятью, но я видел, как многие люди гонялись за этим белым китом, и это оказалось чем-то другим (например, плохой установкой флагов кодека).   -  person vcsjones    schedule 17.12.2014
comment
Сервер 64 битный. Я удивлен, что манипулирование небольшим изображением вызывает у меня эту проблему. Я посмотрю на потребление памяти и т.д.   -  person David Christopher Reynolds    schedule 17.12.2014


Ответы (2)


У нас также были аналогичные проблемы с использованием операций GDI+ на нашем сервере ASP.Net. Ваше упоминание о вашем коде, работающем на сервере, заставило меня подумать, что это может быть та же проблема.

Имейте в виду, что использование классов в пространстве имен System.Drawing не поддерживается на сервере. Фатальным является то, что он может работать какое-то время и вдруг (даже без изменения кода) возникают ошибки.

Нам пришлось переписать значительную часть нашего серверного кода.

Смотрите комментарий:

Предостережение

Классы в пространстве имен System.Drawing не поддерживаются для использования в службах Windows или ASP.NET. Попытка использовать эти классы из одного из этих типов приложений может привести к непредвиденным проблемам, таким как снижение производительности службы и исключения во время выполнения. Поддерживаемую альтернативу см. в разделе Компоненты Windows Imaging.

Источник: http://msdn.microsoft.com/de-de/library/system.drawing(v=vs.110).aspx

person stefan.s    schedule 17.12.2014
comment
Спасибо Стефан, посмотрю. - person David Christopher Reynolds; 17.12.2014
comment
спустя более 5 лет это все еще актуально, я только что пережил кошмар с этим - person Eduardo Portal Geroy; 01.04.2020

Большое спасибо @vcsjones за то, что указал мне правильное направление. Вместо использования image.GetThumbnailImage я вызываю:

public static Image ResizeImage(Image imgToResize, Size size)
    {
        return (Image)(new Bitmap(imgToResize, size));
    }

Проблемная строка кода теперь:

using(Image thumbnail = ResizeImage(image, new Size(m_thumbnailWidth, thHeight)))

Я получил эту строку от Изменить размер изображения С# Теперь это работает!

person David Christopher Reynolds    schedule 17.12.2014