Silverlight: BitmapImage из исключения бросков потока (катастрофический сбой (исключение из HRESULT: 0x8000FFFF (E_UNEXPECTED))) - PullRequest
7 голосов
/ 08 июля 2011

Мне нужно динамически загрузить много (иногда сотни) миниатюр изображений. По соображениям производительности мне нужно делать это в ограниченном количестве запросов, я использую один запрос / ответ для тестирования. Я отправляю двоичные данные для изображений в ответе и загружаю их в BitmapImage, используя MemoryStream. Это работает правильно до тех пор, пока я не загружу более 80 миниатюр, а затем я получаю исключение Catastrophic Failure. Чтобы убедиться, что мои данные не были повреждены, я несколько раз пытался загрузить BitmapImage с одним и тем же байтовым массивом, и он зависал после 80 или около того загрузок.

Вот пример того, как изображение загружается из байтового массива, байтовый массив, как известно, содержит действительные данные изображения (png):

private BitmapImage LoadImage(byte[] imageData)
{
    BitmapImage img = new BitmapImage();
    MemoryStream stream = new MemoryStream(imageData);
    img.SetSource(stream); // Exception thrown here after too many images loaded.
    return img;
}

Затем я использую BitmapImage в качестве источника для элемента Image на странице, но ошибка возникает в строке img.SetSource(...) выше.

Добавление GC.Collect() в цикл загрузки миниатюр позволяет загружать еще несколько изображений, поэтому я думаю, что это как-то связано с управлением памятью, но я не знаю, что можно сделать, чтобы исправить проблема.

Ответы [ 2 ]

6 голосов
/ 04 августа 2011

Я думаю, что цитирование ответа, предоставленного Microsoft в приведенном выше отчете об ошибке, целесообразно, поскольку оно очень лаконично и описывает проблему, а также предлагает рекомендуемое решение:

Когда Silverlight загружает изображениеплатформа сохраняет ссылку и кэширует декодированное изображение до тех пор, пока управление потоком не будет возвращено диспетчеру потоков пользовательского интерфейса.Когда вы загружаете изображения в таком замкнутом цикле, даже если ваше приложение не сохраняет ссылку, ГХ не может освободить изображение, пока мы не освободим нашу ссылку, когда возвращается управление потоком.

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

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

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

0 голосов
/ 18 июля 2011

Я отправил в Microsoft отчет об ошибке для этой проблемы: Исключение катастрофического сбоя, выданное после загрузки слишком большого количества объектов BitmapImage из потока .

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

...