2013-03-21 132 views
0

我已經瀏覽了幾頁類似的查詢,實現了大部分建議,但似乎無法找到迄今爲止工作的任何內容。希望我沒有忽略明顯的東西。C#Picturebox內存泄漏

對,所以我使用AForge.net捕捉圖像。它提供了一個事件,它觸發每個新幀接收,這在我的代碼如下所示:

private void videoSourcePlayer_NewFrame(object sender, ref Bitmap image) 
    { 
     framesRecieved++; 
     try 
     { 
      if (!stopCapturing) 
      { 
       if (pictureBox1.Image != null) 
       { 
        pictureBox1.Image.Dispose(); 
       } 
       pictureBox1.Image = image.Clone(new Rectangle(0, 0, image.Width, image.Height), image.PixelFormat); 
      } 

     } 
     catch { } 
     finally { GC.Collect(); } 
    } 

內存使用情況非常穩定,只要窗口保持靜止,但只要我抓住窗口形式並開始移動它,內存使用量不斷增加。我之所以被認爲可能與picturebox有關,是因爲只要我將「stopCapturing」布爾變爲true,即使我在屏幕上移動窗口,內存也會停止上升。 「stopCapturing」不用於其他任何事情,並且事件繼續正常觸發,唯一的區別是正在顯示在圖片框中的圖像。我對這個原因感到茫然,所以任何幫助將不勝感激。

PS:不確定它是否相關,但我的工作站有2個屏幕。

+0

首先刪除空捕獲和GC.Collect。 – 2013-03-21 10:01:34

+1

不確定是否需要克隆。我以前使用過'新的位圖(圖片)'沒有問題。 – 2013-03-21 12:52:08

回答

0

Bitmap.Clone()做一個淺拷貝,實際的字節仍然由調用者擁有,所以這可能會導致所有類型的麻煩。 您需要進行深層複製。

例如,AForge way

Bitmap bmp = AForge.Imaging.Image.Clone(image); 

還是GDI +的方式(也可以使用lockbits等,爲更好perfs):我不知道爲什麼你克隆

Bitmap bmp = new Bitmap(image.Width, image.Height, image.PixelFormat); 
Graphics g = Graphics.FromImage(bmp); 
g.DrawImageUnscaled(image, Point.Empty); 
0

所有的圖像。這讓我感到當任pictureBox1.Image爲空或只應分配一個新的圖像時,圖像變化的尺寸或像素格式:

private bool BitmapChanged(Bitmap old, Bitmap new) 
{ 
    return old == null || old.PixelFormat != new.PixelFormat || 
     old.Width != new.Width || old.Height != new.Height; 
} 

private Bitmap MakeSimilarBitmap(Bitmap source) 
{ 
    Bitmap copy = new Bitmap(source.Width, source.Height, source.PixelFormat); 
    return copy; 
} 

private void DrawOnto(Image im, Bitmap source) 
{ 
    using (Graphics g = Graphics.FromImage(im)) { 
     g.DrawImage(source, 0, 0); 
    } 
} 

那麼當你得到一個框架,你會做這樣的事情這:

Image im = BitmapChanged(pictureBox1.Image as Bitmap, srcBmp) ? 
          MakeSimilarBitmap(image) : pictureBox1.Image; 
DrawOnto(im, srcBmp); 
bool same = im == pictureBox1.Image; 
if (same) 
    pictureBox1.Invalidate(); 
else { 
    Image old = pictureBox1.Image; 
    pictureBox1.Image = im; 
    old.Dispose(); 
} 
+0

您需要製作副本,因爲圖像歸VideoSource所有。它將自行處理。另請參見:http://www.aforgenet.com/framework/docs/html/63e8ac47-e9c1-d257-c587-c995c5a99b3f.htm – 2013-03-22 09:57:50

+0

我的觀點是,您將內容複製到單個保留位圖中,而不是分配新副本每一幀。 – plinth 2013-03-22 17:31:36