Windows フォーム アプリケーションで、MemoryStream に保存するときに Bitmap.Save が失敗するという問題があります。この問題は (今のところ) 1 台のマシンで断続的に発生するだけのようで、悪い知らせは顧客のサイトにあります。マシン上でデバッグすることはできませんが、問題を 1 行のコードに絞り込むスタック トレースを取得しました。
これが私のコードの要約版です:
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];
}
何が起こっているのでしょうか?私のピクセル バッファは正しいと確信しています。開発/テスト マシンや他の顧客サイトでは常に機能します。
考えられる失敗の理由についての私の考えは、
a. ビットマップ コンストラクターはピクセル データをコピーしませんが、その参照を保持します。メモリが解放されるため、Save は失敗します。この点について MSDN ドキュメントは明確ではありませんが、Bitmap はピクセル データがロックされていると仮定するのではなく、ピクセル データをコピーすると仮定します。
b. ピクセル データが無効なため、Save メソッドが失敗します。私のピクセルデータはピクセルあたり24ビットであるため、これは疑わしいので、私が知る限り、それは無効であってはなりません。
c. .NET フレームワークに問題があります。
他の考えられる失敗の理由について考えていただければ幸いです。アプリに追加のチェックとログ情報を追加して、フィールドに何かを送信できるようにします。