Недостаточно памяти в System.Drawing в службе Windows
Исключение из нехватки памяти при интенсивном использовании system.drawing в моей службе Windows.
вот часть моего кода:
FileStream fs = new FileStream(ImagePath, FileMode.Open, FileAccess.Read);
img = (Image)Image.FromStream(fs).Clone();
Исключение возникает не только в этой точке, но и в других точках, где иногда это касается рисования, обрезки, изменения размера, копирования изображения.
Я всегда выбрасываю все использованные предметы.
Я видел эту статью об "Исключении из нехватки памяти" в system.drawing здесь
и хотя это очень похоже на мой случай, оно отличается, потому что мои данные тестирования представляют собой повторяющуюся цепочку из 40 изображений, поэтому, если есть проблема в одном из них, она должна появиться быстро с первого цикла.
Я видел ограничение, упомянутое здесь
это говорит о том, что мы не должны использовать system.drawing в Win/Web-сервисах.
Хорошо, мне нужно использовать его с Windows-сервисом для массовой обработки изображений, какие есть альтернативы?
4 ответа
Image
объект вы звоните Clone
on не удаляется (и, возможно, в вашем коде есть другие подобные ошибки). Память, используемая такими объектами, освобождается только после запуска финализатора, который требует как минимум 2 цикла GC и OutOfMemoryException
вполне может быть брошено на первый сборщик мусора.
Правильная утилизация должна выглядеть примерно так:
FileStream fs = new FileStream(ImagePath, FileMode.Open, FileAccess.Read);
using(var tmp = Image.FromStream(fs))
img = (Image)tmp.Clone();
// dispose fs an img after use like usually
В качестве альтернативы вы можете прочитать весь файл в MemoryStream
и передать его Image.FromStream
- это означает, что изображение не анализируется дважды, что должно сэкономить дополнительные ресурсы.
Вы используете слишком много памяти слишком быстро и, вероятно, не освобождаете ее как можно скорее.
Вам нужно реорганизовать свой код, чтобы он был более консервативным с вашими ресурсами, и убедитесь, что вы не держитесь за большие объекты дольше, чем нужно, и что вы избавляетесь от своих IDisposables в самое ближайшее время.
Этот процесс не легок, и не может быть полностью отвечен на форуме как этот.
Почему вы клонируете изображение? В вашем примере вы читаете данные из файла, а затем создаете копию. Не требуется много, чтобы вызвать исключение нехватки памяти в службе с высокой пропускной способностью объекта.
Вы можете просто сделать это:
var img = Image.FromFile(ImagePath);
Это может быть не актуально, но...
У меня были проблемы при работе с растровыми изображениями в C++, при получении ошибок нехватки ресурсов из низкоуровневых оконных API. Кажется, это происходит из-за того, что куча внутренних ресурсов Windows не может обрабатывать / выделять битовые карты / битовые разделы, когда рисование выполняется с помощью битовых битов и тому подобного.
Не знаю, может ли что-то подобное в этой цепочке отключить библиотеки dotnet. Где-то в MSDN есть инструмент, который устанавливает драйвер устройства и может использоваться для изучения различных куч рабочего стола (не знаю, как это может относиться к сервисам.) Я думаю (давно, с тех пор, как я его использовал), он показывает проценты, использованные / доступно - хотя это может быть некоторым показателем, я подозреваю, что фрагментация этих областей может также привести к ошибкам - к сожалению, я не смог полностью устранить свои проблемы, но этот инструмент может помочь вам диагностировать ваши. (Похоже, инструмент можно назвать "dheapmon".)