GDI + System.Drawing.Bitmap выдает ошибку Параметр периодически недействителен

У меня есть код C# в приложении ASP.Net, который делает это:

Bitmap bmp = new Bitmap (1184, 1900);

И иногда выдает исключение «Параметр недействителен». Теперь я гуглил, и, очевидно, GDI + печально известен тем, что выбрасывает случайные исключения, и у многих людей была эта проблема, но ни у кого нет решения! Я проверил систему, и в ней много оперативной памяти и места для подкачки. Раньше, если я делаю iisreset, проблема исчезает, но она возвращается через несколько дней. Но я не уверен, что вызвал утечку памяти, потому что, как я сказал выше, много оперативной памяти + свопинга.

У кого-нибудь есть решения?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
13
0
15 580
6

Ответы 6

Вам не только нужно достаточно памяти, она должна быть непрерывной. Со временем память становится фрагментированной, и становится все труднее находить большие блоки. Для этого не так много хороших решений, кроме создания изображений из меньших растровых изображений.

new Bitmap (x, y) в значительной степени просто необходимо выделить память - предполагая, что ваша программа не повреждена каким-либо образом (есть ли какой-либо небезопасный код, который может повредить кучу), тогда я бы начал с этого сбоя выделения. Необходимость в непрерывном блоке может привести к сбою, казалось бы, небольшого выделения. Фрагментация кучи - это то, что обычно решается с помощью специального распределителя - я не думаю, что это хорошая идея в IIS (или возможная).

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

Одна стратегия, которую я видел, - это предварительно выделить несколько больших блоков памяти (в вашем случае Bitmaps) и рассматривать их как пул (получить и вернуть их в пул). Если они вам нужны только на короткий период времени, вы можете просто сохранить несколько в памяти и поделиться ими.

Растровое изображение размером 1184x1900x32 бита составляет ~ 9 мегабайт. Неужели это слишком много, чтобы надежно требовать непрерывный блок?

Chris 25.09.2008 07:37

Я только что получил ответ от службы поддержки Microsoft. Видимо, если посмотреть сюда:

http://msdn.microsoft.com/en-us/library/system.drawing.aspx

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

Далее - может ли кто-нибудь порекомендовать аналогичную библиотеку для открытия файла gif, наложения текста и его повторного сохранения?

Все, что я видел на сегодняшний день в своем контексте, связано с утечками памяти / дескрипторами. Я рекомендую вам взглянуть свежим взглядом на свой код.

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

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

http://blog.lavablast.com/post/2007/11/The-Mysterious-Parameter-Is-Not-Valid-Exception.aspx

Я думал, что это может быть так, поэтому я убедился, что вызову функцию Dispose в объекте system.bitmap, разве это не решило бы проблему?

Chris 09.10.2008 06:03

Прекратите использовать GDI + и начните использовать классы WPF Imaging (.NET 3.0). Это основная очистка классов GDI +, настроенная для повышения производительности. Кроме того, он устанавливает «цепочку растровых изображений», которая позволяет вам легко выполнять несколько действий с растровыми изображениями эффективным способом.

Узнайте больше, прочитав о BitmapSource

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

using System.Windows.Media.Imaging;
class Program {
    public static void Main(string[] args) {
        var bmp = new WriteableBitmap(1184, 1900, 96.0, 96.0, PixelFormat.Bgr32, null);
    }
}

Для всех, кому интересно, я собираюсь использовать библиотеки Mono.Cairo из моно-дистрибутива C# вместо использования system.drawing. Если я просто перетащу файлы mono.cairo.dll, libcairo-2.dll, libpng13.dll и zlib1.dll из версии mono для Windows в ту же папку, что и мой исполняемый файл, тогда я смогу разрабатывать в Windows с помощью Visual Studio 2005 и все прекрасно работает.

Обновление - я проделал все вышеописанное и провел стресс-тестирование приложения, и теперь все, похоже, работает без сбоев, и для загрузки используется на 200 МБ меньше оперативной памяти. Очень счастлив.

Классы в пространстве имен System.Drawing не поддерживаются для использования в службах Windows или ASP.NET.

Для поддерживаемой альтернативы см. Компоненты Windows Imaging (msdn), собственную библиотеку, на которой, по иронии судьбы, основан System.Drawing.

Другие вопросы по теме