нехватка памяти при использовании control.BackgroundImage = Image.FromStream (memStream); - PullRequest
6 голосов
/ 15 октября 2011

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

control.BackgroundImage = Image.FromStream(memStream);

, но при использовании этого кода возникает "Недостаточно памяти " исключение.но при использовании

control.Image = Image.FromStream(memStream);

или

control.BackgroundImage = Image.FromFile(fileSource);

, это работа.

размер файла изображения составляет 5 КБ.

 if (System.IO.File.Exists(imgSource))
 {
  using (FileStream localFileStream = new FileStream(imgSource, FileMode.Open))
  {
  using (MemoryStream memStream = new MemoryStream())
  {
   int bytesRead;
   byte[] buffer = new byte[1024];

   while ((bytesRead = localFileStream.Read(buffer, 0, buffer.Length)) > 0)
   {
      memStream.Write(buffer, 0, bytesRead);
   }
   retIMG = Image.FromStream(memStream);

   pictureBox1.Image = retIMG;      // is work
   label1.Image = retIMG;       // is work
   button1.Image = retIMG;      // is work
   button1.BackgroundImage = retIMG;    // don't work
   groupBox1.BackgroundImage = retIMG;  // don't work
   panel1.BackgroundImage = retIMG; // don't work
  }
  }
 }

Я думаю, что ошибка в .net Framework.пожалуйста, вы мне поможете?

Ответы [ 2 ]

8 голосов
/ 15 октября 2011

Прочтите замечания по Image.FromStream по MSDN :

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

Поэтому, если вы удалите using вокруг создания вашего MemoryStream, ваш код будет работать нормально.

Конечно, вы должны предпочтительно утилизировать MemoryStream, когда вам больше не нужен созданный вами Image, хотяв этом случае, скорее всего, не будет никакого вреда, если вы не вызовете Dispose() и не предоставите GC возможность забрать его, когда он не используется.

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

7 голосов
/ 15 октября 2011

Предоставление некоторого фона, чтобы добавить к правильному ответу DeCaf.GDI + очень старается избежать копирования пикселей растрового изображения.Это дорого, растровые изображения, занимающие десятки мегабайт, не являются чем-то необычным.Когда вы загружаете растровое изображение из файла с помощью конструктора Bitmap или Image.FromFile (), тогда GDI + создает файл с отображением в памяти.Пиксели вставляются по требованию, только при необходимости.Очень эффективно, но это ставит блокировку на файл.Ясно, что вы пытались избежать этой блокировки в этом коде.

Вы действительно избегаете этой блокировки, загружая байты в память самостоятельно с помощью MemoryStream.Но тот же принцип все еще применяется, GDI + все еще не копирует пиксели и читает только из потока, когда это необходимо.Это идет не так, когда вы Dispose () поток.Очень трудно диагностировать, потому что исключение возникает позже , обычно, когда нужно нарисовать растровое изображение.Это бомба в коде рисования, у вас нет кода для просмотра, кроме Application.Run ().С дрянным сообщением об исключении, GDI + имеет только несколько кодов ошибок.У вас нет нехватки памяти, это выглядит так только в GDI +, иначе невозможно понять, почему поток внезапно перестает читаться.

По крайней мере, часть проблемы вызванаочень неудобной реализацией MemoryStream.Dispose ().Dispose предназначен для освобождения неуправляемых ресурсов.Поток памяти не имеет, он только владеет памятью.Об этом уже позаботится сборщик мусора.К сожалению, они все равно это реализовали.Не путем утилизации чего-либо, поскольку нечего утилизировать, а путем пометки MemoryStream как нечитаемогоЧто вызывает ошибку в GDI +, когда он пытается читать при рисовании растрового изображения.

Поэтому просто удалите оператор , используя , чтобы избежать использования MemoryStream для решения вашей проблемы.И не беспокойтесь о его утилизации позже, когда растровое изображение больше не используется.Утилизировать нечего, сборщик мусора автоматически освобождает память.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...