1

我有以下循环运行的代码。

public void Test(Bitmap bmp)
{
   FormatConvertedBitmap fBitmapSource = new FormatConvertedBitmap();
   PngBitmapEncoder pngBitmapEncoder = new PngBitmapEncoder();
   BitmapImage bi = new BitmapImage();

   using (MemoryStream ms = new MemoryStream())
   {
      bmp.Save(ms, ImageFormat.Png);
      bmp.Dispose();
      bmp = null;

      bi.BeginInit();
      bi.StreamSource = ms;
      bi.EndInit();

      BitmapPalette pallete = new BitmapPalette(bi, 256);
      ...

最后一行

BitmapPalette pallete = new BitmapPalette(bi, 256);

有时会抛出以下异常

Insufficient memory to continue the execution of the program.at System.Windows.Media.Imaging.BitmapPalette..ctor(BitmapSource bitmapSource, Int32 maxColorCount)

有任何想法吗 ?我显然有足够的内存来继续执行。

4

1 回答 1

2

托管程序中还有其他 OutOfMemoryException 来源与托管内存不足无关。当它转换旧本机代码返回的错误代码时也会引发异常。就像 COM 方法调用可以返回的 E_OUTOFMEMORY 错误一样。与您的情况相关,由 GDI+ 提供。其中只有 20 个不同的错误代码表示失败,您会发现它们记录在这个答案中。其中之一是 OutOfMemory。

这可能意味着不止一件事。用完非托管内存,GDI+ 用来存储位图像素的那种内存肯定是有可能的。这也可能意味着您的进程已用完可用的 GDI 对象句柄,Windows 规定了 10,000 个 GDI 句柄的句柄配额。顺便说一句,这是一个巨大的数字,超过该配额几乎总是表明代码中存在错误。手柄泄漏。在托管程序的情况下,这几乎总是由于忘记使用 Image.Dispose() 方法并且没有足够频繁地运行垃圾收集器以允许终结器释放句柄。

可悲的是,它甚至可能由损坏的位图数据触发,这在您的情况下不太可能,因为您在分配调色板时轰炸了。这表示句柄泄漏,应该在 Taskmgr.exe 的“进程”选项卡中很容易看到。查看 + 选择列并勾选 GDI 对象。在测试过程中,请密切注意过程的显示值。稳步增长的数字会带来麻烦,当它达到 10,000 时,节目就结束了。另请查看“提交大小”列,这可能会显示您在消耗过多非托管内存时遇到的麻烦。

于 2012-05-30T13:32:13.190 回答