У меня есть код C# в приложении ASP.Net, который делает это:
Bitmap bmp = new Bitmap (1184, 1900);
И иногда выдает исключение «Параметр недействителен». Теперь я гуглил, и, очевидно, GDI + печально известен тем, что выбрасывает случайные исключения, и у многих людей была эта проблема, но ни у кого нет решения! Я проверил систему, и в ней много оперативной памяти и места для подкачки. Раньше, если я делаю iisreset, проблема исчезает, но она возвращается через несколько дней. Но я не уверен, что вызвал утечку памяти, потому что, как я сказал выше, много оперативной памяти + свопинга.
У кого-нибудь есть решения?





Вам не только нужно достаточно памяти, она должна быть непрерывной. Со временем память становится фрагментированной, и становится все труднее находить большие блоки. Для этого не так много хороших решений, кроме создания изображений из меньших растровых изображений.
new Bitmap (x, y) в значительной степени просто необходимо выделить память - предполагая, что ваша программа не повреждена каким-либо образом (есть ли какой-либо небезопасный код, который может повредить кучу), тогда я бы начал с этого сбоя выделения. Необходимость в непрерывном блоке может привести к сбою, казалось бы, небольшого выделения. Фрагментация кучи - это то, что обычно решается с помощью специального распределителя - я не думаю, что это хорошая идея в IIS (или возможная).
Чтобы узнать, какая ошибка возникает из-за нехватки памяти, попробуйте просто выделить гигантский Bitmap в качестве теста - посмотрите, какую ошибку он выдает.
Одна стратегия, которую я видел, - это предварительно выделить несколько больших блоков памяти (в вашем случае Bitmaps) и рассматривать их как пул (получить и вернуть их в пул). Если они вам нужны только на короткий период времени, вы можете просто сохранить несколько в памяти и поделиться ими.
Я только что получил ответ от службы поддержки 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, разве это не решило бы проблему?
Прекратите использовать 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.
Растровое изображение размером 1184x1900x32 бита составляет ~ 9 мегабайт. Неужели это слишком много, чтобы надежно требовать непрерывный блок?