2016-05-17 198 views
0

我目前正在使用AForge DLL來呈現實況視圖的圖片框上的視頻。我確實有一個視頻幀功能,以確定是否將WriteFrame或當前的圖片框框架截圖爲JPG。System.Drawing參數無效

但我遇到了一個問題,有時程序會提示出錯的參數無效或對象已被用在其他地方。我確實試圖找到解決方案來解決它,我很確定我確實在圖像和克隆圖像上進行了處理,但問題仍然存在。

你能幫我解釋我的程序有什麼問題嗎?

void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs) 
     { 
      //your code using bmp object 
      if (D1Pic.BackColor == Color.Green) 
      { 
       video = (Bitmap)eventArgs.Frame.Clone(); 
       if (livePreview.Image != null) 
       { 
        //Dispose the resources 
        this.Invoke(new MethodInvoker(delegate() { livePreview.Image.Dispose(); })); 
       } 
       livePreview.Image = (Bitmap)eventArgs.Frame.Clone(); 
       imgclone = (Image)livePreview.Image.Clone(); 
       FileWriter.WriteVideoFrame(video); 
      } 
      else 
      { 
       video = (Bitmap)eventArgs.Frame.Clone(); 
       if (livePreview.Image != null) 
       { 
        //Dispose the resources 
        this.Invoke(new MethodInvoker(delegate() { livePreview.Image.Dispose(); })); 
        this.Invoke(new MethodInvoker(delegate() { video.Dispose(); })); 
       } 
       livePreview.Image = (Bitmap)eventArgs.Frame.Clone(); 
       imgclone = (Image)livePreview.Image.Clone(); 
      } 
      video.Dispose(); 
      livePreview.Refresh(); 

這裏是堆棧跟蹤錯誤:

{"Parameter is not valid."} 
    at System.Drawing.Image.get_Width() 
    at System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode mode) 
    at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe) 
    at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer) 
    at System.Windows.Forms.Control.WmPaint(Message& m) 
    at System.Windows.Forms.Control.WndProc(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 

更新的代碼:

var newFrame = (Bitmap)eventArgs.Frame.Clone(); 
       this.Invoke(new MethodInvoker(delegate() 
       { 
        if (livePreview.Image != null) 
        { 
         livePreview.Image.Dispose(); 
        } 
        livePreview.Image = newFrame; 
       })); 
       imgclone = (Bitmap)eventArgs.Frame.Clone(); 

       //Write frame into video 
       if (D1Pic.BackColor == Color.Green) 
       { 
        video = (Bitmap)eventArgs.Frame.Clone(); 
        FileWriter.WriteVideoFrame(video); 
       } 
+0

錯誤發生在哪條線上? –

+0

@JeremyThompson livePreview.Refresh() – Marcus

+0

改爲嘗試'livePreview.Invalidate()'。 –

回答

1

要調用在UI線程livePreview.Image.Dispose(),但你沒有設置livePreview.Image事後空。

因此,在您處置livePreview.Image的時間與爲其分配新圖像的時間之間,livePreview.Image指向已處理的對象。

因此,我認爲偶爾您的圖片盒會在這段時間內嘗試繪製自己,並在嘗試訪問其(處置)Image屬性時失敗。

的解決辦法是:

if (livePreview.Image != null) 
{ 
    //Dispose the resources 
    this.Invoke(new MethodInvoker(delegate() { 
     livePreview.Image.Dispose(); 
     livePreview.Image = null; 
    })); 
} 

甚至更​​好,在相同的步驟分配的新形象:

var newFrame = (Bitmap)eventArgs.Frame.Clone(); 
this.Invoke(new MethodInvoker(delegate() { 
    if (livePreview.Image != null) 
    { 
     livePreview.Image.Dispose(); 
    } 
    livePreview.Image = newFrame; 
})); 

在一般情況下,你需要了解與您不同的位圖對象發生。任何保持對已經處理的位圖的引用都是一個問題。

+0

對於視頻也一樣嗎? 我的意思是視頻錄製的FileWriter – Marcus

+0

我沒有看到這個部分的問題,它都發生在同一個線程上,據我所知。 – Blorgbeard

+0

請參閱我的更新代碼,我對代碼進行了更改。代碼可以嗎? – Marcus