Как определить, вызовет ли загрузка изображения исключение OutOfMemory в .NET? - PullRequest
5 голосов
/ 08 июля 2010

У меня есть приложение, написанное с использованием .NET 3.5 SP1, которое загружает изображения с внешнего сайта и отображает их конечным пользователям.В редких случаях мои пользователи сталкиваются с ошибками OutOfMemory, потому что они загружают огромные изображения.Иногда необработанные данные, связанные с этими изображениями, являются большими, но чаще размеры изображений огромны.Я понимаю, что, возможно, мне никогда не удастся обойти тот факт, что эти ошибки OOM выбрасываются для определенных изображений.Однако было бы ОЧЕНЬ полезно, если бы я мог каким-то образом определить, приведет ли загрузка определенного изображения к проблеме OOM, прежде чем я попытаюсь загрузить изображение.

Данные для изображений загружаются в потокзатем само изображение превращается в System.Drawing.Image путем вызова System.Drawing.Image.FromStream (stream).У меня нет возможности сначала сохранить эти изображения на диске.Они должны быть загружены через память.

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

Ответы [ 6 ]

4 голосов
/ 08 июля 2010

Вы можете использовать класс MemoryFailPoint для проверки доступности памяти.

Наилучшее

1 голос
/ 08 июля 2010

Я уже согласился с ответом @Vagaus, но я хотел добавить, что вы должны выделить буфер только один раз и попытаться использовать его повторно.Если вы постоянно выделяете и освобождаете большой буфер, вы наверняка столкнетесь с проблемой OOM из-за фрагментации в куче.

1 голос
/ 08 июля 2010

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

1 голос
/ 08 июля 2010

У тебя проблема с яйцом и курицей. Чтобы сделать какое-то предположение, вам нужно знать размер изображения. Вы не знаете размер, пока не загрузите его.

В любом случае это не очень полезно. Получите ли вы OOM, действительно зависит от того, насколько фрагментирована адресная область виртуальной памяти. И это не легко найти в Windows. Требуется API-функция HeapWalk (), и это нездоровая функция. Проверьте мелкий шрифт в статье библиотеки MSDN для этого. Особенно плохо в управляемой программе, не используйте ее.

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

Если вы как-то знаете размер фронта, тогда вы вполне можете с уверенностью предположить, что ширина * высота * 4> 550 МБ не будет работать в 32-битной программе. Этот лимит быстро снижается после некоторого запуска.

1 голос
/ 08 июля 2010

Вы можете посмотреть на этот вопрос и посмотреть, поможет ли он: Как надежно получить размеры изображения в .NET без загрузки изображения?

Идея заключается в том, чтобы загрузитьтолько часть общего изображения (в частности, заголовок), чтобы вы могли прочитать метаданные.Затем вы можете использовать полученную информацию, чтобы определить, насколько велико изображение, и запретить его полную загрузку, если увидите, что оно будет слишком большим.

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

1 голос
/ 08 июля 2010

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

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

...