カメラとインターフェイスするフォームを含むアプリケーションがあります。ユーザーはフォームからカメラを制御し、写真を撮ったり、WinForms PictureBox
に表示したり、別のフォームを開いて表示されている画像を編集したり、その画像をディスクに保存することができます。私たちの顧客は、断続的なAccessViolationExceptionsについて不平を言っています。午後になってから、PictureBox.Image
をMemoryStream
に保存する前に、GC.Collect
を強制して私の開発環境で問題を再現するための信頼できる方法を見つけました。ガベージコレクションの直後にPictureBox.Imageを保存しようとすると、AccessViolationExceptionが発生する
int w = videoInfoHeader.BmiHeader.Width;
int h = videoInfoHeader.BmiHeader.Height;
int stride = w * 3;
GCHandle handle = GCHandle.Alloc(savedArray, GCHandleType.Pinned);
long scan0 = (long)handle.AddrOfPinnedObject();
scan0 += (h - 1) * stride; //image is upside down, so start at the bottom (I guess bottom-up bitmaps still scan left-to-right?)
Bitmap b = new Bitmap(w, h, -stride, PixelFormat.Format24bppRgb, (IntPtr)scan0);
handle.Free();
Image old = pictureBog.Image;
pictureBox.Image = b;
if (old != null)
old.Dispose();
//Show picturebox, and let user use the form
:
私たちは、このような私たちのPictureBox
コントロールを作成します
//GC.Collect()
using (MemoryStream stream = new MemoryStream())
{
pictureBox.Image.Save(stream, ImageFormat.Jpeg); //AccessViolationException here if GC.Collect() is uncommented.
byte[] pic = stream.ToArray();
//Do stuff with pic and open editor form
}
私はRandomly occurring AccessViolationException in GDI+からGCの移動は、アンマネージコードの下から出て詰め込むので、あなたが起きてからこれを防ぐために「ピン」の管理対象オブジェクトに持っている問題があると指摘しました。 PictureBox
にデータを入力したときにこれを行っていることがわかりますが、画像をPictureBox
から引き出しているときは表示されません。バイト配列は単なる配列であるため、ソースバイト配列を「ピン」する必要があることを理解しています。しかし、イメージを保存するときに私が "ピン"しようとするもの、つまりMemoryStreamを知りませんか? Bitmap.Save(Stream)は、必要に応じて自動的に処理できるほどスマートであると思います。さらに、バッファは、それがどんどんいっぱいになると再割り当てされる必要があるので、ピン設定は私にはあまり意味がありません。誰でも何がここに悪いメモリアクセスを引き起こしているか考えている?
イメージデータを取り出して元のバイト配列を保持し、それからBitmap
を作成して新鮮なコピーから保存するときは、PictureBox
を使用しないでください。これはうまくいくと思われますが、これはただの偶然であり、実際の問題がまだ残っているかどうかはわかりません。
BitmapコンストラクタのMSDNのドキュメントをご覧ください。 「呼び出し元は、scan0パラメータで指定されたメモリブロックの割り当てと解放を担当しますが、メモリは関連するビットマップが解放されるまで解放されるべきではありません。コード内で固定されたメモリを解放していますが、ビットマップはもう使用しません。すぐにガベージコレクションを実行すると、すぐに対応する例外が発生します。それ以外の場合は、GCが実行を決定したときにいつでも例外が発生する可能性があります。 – KBO