Исключение GDI + при сохранении изображения в формате PNG

Приложение ASP.NET на моем сервере начинает бросать исключение GDI + после запуска в течение нескольких дней. После перезапуска сервера все работает нормально в течение нескольких дней, а затем внезапно это исключение происходит снова. После первого раза это происходит каждый раз, когда я пытаюсь сохранить изображение PNG, пока я не перезапущу его снова.

Когда я пытаюсь сохранить изображение в формате JPEG, он отлично работает.

Когда я запускаю этот код из моего проекта, он терпит неудачу:

var path = @"C:\Project\images\logo.png";
var image = Image.FromFile(path);

using (var ms = new MemoryStream())
{
    image.Save(ms, ImageFormat.Png);     // Fails here on GDI+ exception.
    //image.Save(ms, ImageFormat.Jpeg);  // JPEG works somehow
}

Снова: когда я перезапускаю удаленный рабочий стол и запускаю этот код, он работает в течение нескольких дней и в какой-то момент внезапно начинает терпеть неудачу снова и снова.

Я пробовал:

  • Сделать консольное приложение с тем же кодом и запустить его в RDP, где находится проект. Он работал нормально!

  • Множество различных вариантов кодов, которые были предложены более чем в 10 статьях, которые я прочитал по этой теме.

  • GCI.Collect() - без помощи.

  • Проверяют все папки, у которых есть права на запись (возможно, что-то есть с IIS?).

  • Далее.

Я думаю, что это должна быть какая-то конфигурация, которая внезапно меняется из-за чего-то, и я не могу понять, что это может быть.

Ответ 1

После перезапуска сервера все работает отлично в течение нескольких дней, а затем внезапно это исключение происходит, и после первого раза это произойдет, каждый раз, когда я пытаюсь сохранить изображение PNG, я снова перезапущу его.

Звучит как утечка памяти для меня. С какой версией .NET это скомпилировано? Какая серверная ОС работает?

Вы можете начать с включения изображения в блок использования:

var path = @"C:\Project\images\logo.png";
using (Image image = Image.FromFile(path))
{
    using (var ms = new MemoryStream())
    {
        image.Save(ms, ImageFormat.Png);
    }
}

Эта ссылка Я считаю, относится к вашему делу.

Ответ 2

Он выдает ошибку GDI +, потому что один из ваших объектов не расположен, поэтому лучше удаляйте используемый объект.

Если вы получаете эту ошибку, я могу сказать, что ваше приложение не имеет права на запись в какой-либо каталог.

GDI + ограничивает высоту изображения до 65534

Всегда рекомендуется использовать инструкцию using. Который никогда не забывает распоряжаться объектом, даже если код генерирует исключение.

var path = @"C:\Project\images\logo.png";
using (Image image = Image.FromFile(path))
{
      using (var ms = new MemoryStream())
      {
            image.Save(ms, ImageFormat.Png); //fails here on GDI+ exception.
            //image.Save(ms, ImageFormat.Jpeg); //Jpeg Works somehow
      }
}

Метод FromFile блокирует файл, поэтому для чтения изображения используйте метод Image.FromStream():

byte[] bytes = System.IO.File.ReadAllBytes(filename);
System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);
using (var ms = new MemoryStream())
{
      image.Save(ms, ImageFormat.Png); //fails here on GDI+ exception.
      //image.Save(ms, ImageFormat.Jpeg); //Jpeg Works somehow
}

Ответ 3

В принципе, если у вас есть одноразовые объекты... Утилизируйте их! Изображение одноразовое, и в качестве растрового изображения оно использует ресурсы Windows. Если вы не распоряжаетесь, ресурсы Windows не освобождаются, пока вы не отключите приложение. Таким образом, вам нужно избавиться от любого созданного образа.