新しいビットマップを作成し、「get」アクセサーを介して返そうとすると、メモリ不足の例外が発生します。Bitmap のサイズは 640x480 で、深さは Int32 です。
私の疑いは、C# ガベージ コレクターがこれらの古いビットマップを削除できないということです。これは、それらが私の変数へのアクセサーで返されているためです。2GB をはるかに超える空き容量があるので、この「小さい」イメージが大量のメモリを消費しているとは思えません。残念ながら、スレッド ロックの問題 (スレッド間で画像をロックする際の問題) により、ビットマップを新しくする必要があります。コードは次のとおりです。
public Bitmap LiveFrame { get { return GetFrame(500); } }
.....
private Bitmap GetFrame(int timeout)
{
Bitmap ret = null;
//CLEyeCameraGetFrame places image data into this._PrivateBitmap
bool success = CLEyeCameraGetFrame(_Camera, _PtrBmpPixels, timeout);
if(success)
ret = new Bitmap(this._PrivateBitmap);
return ret;
}
アンマネージ コードに関する注意: CLEyeCameraGetFrame はアンマネージ DLL 内にあります。コードの前半で Marshal.AllocHGlobal を使用して _PtrBmpPixels を割り当て、アプリを閉じるときに解放するまで触れません。_PtrBmpPixels は、IntPtr 引数 "scan0" を受け入れるコンストラクターを介して Bitmap _PrivateBitmap の作成に使用されました。したがって、_PtrBmpPixels が CLEyeCameraGetFrame を介して更新されるたびに、_PrivateBitmap も更新されます。
PcitureBox ビットマップを再利用する前に破棄することでこれを修正しようとしましたが、PictureBox の表示が壊れました。2 つの異なる PictureBox/ImageBox を更新する 2 つのスレッドがあります。
lock (_CameraLocker)
{
if (_VideoPlaying)
{
try{
if (pbLiveFeed.Image != null)
pbLiveFeed.Image.Dispose();
pbLiveFeed.Image = _Camera.LiveFrame;
pbLiveFeed.Invalidate();
}catch (Exception ex) { }
}
....
lock (_CameraLocker)
{
try{
if (ibProcessed.Image != null)
ibProcessed.Image.Dispose();
procImage = new Image<Bgra, Int32>(_Camera.LiveFrame);
procImage.Draw(new Rectangle(10, 20, 20, 15), new Bgra(1.0, 1.0, 1.0, 1.0), 5);
ibProcessed.Image = procImage;
}catch (Exception ex) { }
}
ガベージ コレクションが原因でしょうか。get アクセサーから newed オブジェクトを返すのは安全ではないですか?