位图调色板 内存不足异常

本文关键字:异常 内存不足 调色板 位图 | 更新日期: 2023-09-27 18:35:56

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

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)

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

位图调色板 内存不足异常

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

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

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