2012-02-03 2 views
2

Прямо сейчас у меня есть приложение, которое загружает кучу миниатюр в элементы управления PictureBox. Иногда более ста за раз. Изображения создаются с использованием Image.FromStream (MemoryStream), а поток памяти представляет каждый файл JPG.Загрузка изображения и зависимость потока/файла

В настоящее время, как только я звоню в Image.FromStream, я назначаю ссылку на окно с изображением, а затем сразу после того, как я Flush() и Dispose() поток.

Согласно документации, я не должен выпускать поток, пока не закончится с изображением. Однако у меня не было никаких ошибок. Элементы управления PictureBox могут воспроизводиться в течение всего дня с помощью уменьшенных изображений даже после того, как потоки памяти уже давно удалены.

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

  • Если Bitmap имеет зависимость от потока памяти или файловый поток, он будет распоряжаться источником при утилизации этого? Или это только тогда, когда он создает поток, используя Bitmap.FromFile?

  • Является ли утилитой MemoryStream немедленно, как будто я рассматриваю ОК? PictureBox должен каким-то образом кэшировать изображение. У меня никогда не было ошибки, потому что мне не нужно касаться изображения после его установки.

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

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

Есть ли хороший способ заставить изображение быть предварительно загруженным? Каковы расхождения между Image.FromFile, Image.FromStream, новым Bitmap (fileName) и т. Д.? Может ли кто-нибудь из них сразу загрузить все байты или задержится до тех пор, пока они не понадобятся?

Вот мой код:

MemoryStream ms = new MemoryStream(bytes); // byte[] array 
pictureBox.Image = Image.FromStream(ms); 
ms.Flush(); 
ms.Dispose(); 

ответ

1

GDI +, который лежит в основе классов изображения, требует, чтобы поток источника оставался открытым, пока изображение существует для правильной работы. Также неплохо писать изменения в исходном потоке, пока Image использует его. Изменения должны быть сохранены в другом потоке.

Все производное от изображения использует поток под обложками. Их поведение по загрузке одинаково.

Изображение не закрывает или не удаляет поток, который был предоставлен ему через FromStream. Тебе нужно самому справиться.

Кроме того, вызов Flush on Stream имеет эффект, если Stream был записан в.

Если вы хотите, чтобы улучшить поведение пользовательского интерфейса для ваших PictureBoxes, попробуйте следующее:

  1. Set InitialImage в небольшой вращателе GIF.
  2. Установите WaitOnLoad в false.
  3. Укажите изображение, установив ImageLocation. (Вы можете использовать файл или URL-адрес в нем.)
  4. Загрузите изображения асинхронно с помощью метода LoadAsync.
0

1)

Если Bitmap имеет зависимость от потока памяти или файлового потока, будет его отчуждать источник при утилизации этого? Или это только тогда, когда создает сам поток, используя Bitmap.FromFile?

Взгляните на Image.FromStream Method (Stream, Boolean):

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

2)

PictureBox должен быть кэширование изображения в некотором роде.У меня никогда не было ошибки, потому что мне не нужно прикасаться к изображению после его установки.

Вы просто должны не выбрасывайте экземпляр изображения, так как он был назначен на PictureBox (т.е. изображение коробки использует его), и в то время как PictureBox использует его. В противном случае PictureBox попытается использовать удаленное изображение, и это должно привести к некоторым «нехорошим» последствиям.

PictureBox.Image Property:

Примечание Если вы хотите использовать один и тот же образ в нескольких PictureBox управления, создать клон изображения для каждого PictureBox. Доступ к тому же изображению из нескольких элементов управления вызывает исключение.

Update:

образца с практически по тому же сценарию: HOW TO: Copy a Picture from a Database Directly to a PictureBox Control with Visual C#.

+0

Вы прочитали мои результаты из моего тестирования? Я выбрал поток, используемый для Image.FromStream, но все же мои элементы управления PictureBox все еще красивы. Я просто пытаюсь понять, почему это происходит, чтобы лучше понять, как получить лучшую производительность от PictureBoxes. –

+0

@Moozhe, я полагаю, MemoryStream Dispose() фактически не уничтожает ** память из-за реализации MemoryStream: он использует простой массив байтов (который будет собирать мусор). Не могли бы вы попробовать эксперимент с классом FileStream? –

+0

Это звучит правильно, поскольку MemoryStream не выделяет память ... PictureBox должен содержать ссылку на адрес памяти массива byte [], поэтому он не собирает мусор. –

Смежные вопросы