3

我在 Windows 窗体应用程序中遇到问题,当我保存到 MemoryStream 时,Bitmap.Save 失败。该问题似乎仅在一台机器上间歇性发生(到目前为止),而坏消息是在客户站点上。我无法在机器上调试,但我得到了一个堆栈跟踪,将问题缩小到一行代码。

这是我的代码的精简版本:

byte[] ConvertPixelsToBytes()
{
    // imagine a picture class that creates a 24 bbp image, and has
    // a method to get an unmanaged pixel buffer.
    // imagine it also has methods for getting the width,
    // height, pitch 

    // I suppose this line could return a bad address, but 
    // I would have expected that the Bitmap constructor would have 
    // failed if it was
    System.IntPtr pPixels = picture.GetPixelData();

    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(
            picture.width(),
            picture.height(),
            picture.pitch(),
            System.Drawing.Imaging.PixelFormat.Format24bppRgb,
            pPixels );

    // This line doesn't actually free the memory, but it could be freed in a 
    // background thread
    // (2)
    picture.releasePixelData(pPixels);

    System.IO.MemoryStream memStream = new System.IO.MemoryStream();
    try
    {
        // I don't see how this line could fail, but it does
        // (3)
        bmp.Save(memStream, System.Drawing.Imaging.ImageFormat.Bmp);
        return memStream.ToArray();
    }
   catch(System.Runtime.InteropServices.ExternalException e)
   {
       // e.Message is the very helpful " A generic error occurred in GDI+."
   }
   finally
   {
       memStream.Dispose();
   }
   return new byte[0];
}

知道会发生什么吗?我很确定我的像素缓冲区是正确的,它始终可以在我们的开发/测试机器和其他客户站点上运行。

我对失败的可能原因的看法是

一种。位图构造函数不会复制像素数据,而是保留对它的引用,由于内存被释放,保存失败。我没有发现 MSDN 文档在这一点上很清楚,但我假设 Bitmap 复制像素数据而不是假设它被锁定。

湾。像素数据无效,导致 Save 方法失败。我对此表示怀疑,因为我的像素数据是每像素 24 位,所以据我所知它不应该是无效的。

C。.NET 框架存在问题。

如果您对其他可能的失败原因有任何想法,我将不胜感激,这样我就可以在我的应用程序中添加额外的检查和日志记录信息,这样我就可以将一些东西发送到现场。

4

2 回答 2

5

该 Bitmap 构造函数的 MSDN 文档毫无疑问:

备注 调用者负责分配和释放由scan0 参数指定的内存块,但是,在释放相关Bitmap 之前不应释放内存。

于 2009-02-06T23:17:38.710 回答
2

你试过搬家吗

   picture.releasePixelData(pPixels);

   finally
   {
       memStream.Dispose();
       picture.releasePixelData(pPixels);
   }

这听起来绝对像是一个线程问题(特别是因为您声明 releasePixelData 可能发生在后台线程上)。线程问题总是只发生在一台机器上,而且总是在客户端机器上(可能是因为他们只有 256Megs 的内存或者一些荒谬的东西,垃圾收集器很早就开始了,或者机器有四核并且您的开发人员机器是双核或其他东西)。

于 2009-02-06T20:11:04.763 回答