使用.Dispose以线程安全的方式

时间:2013-04-15 15:16:38

标签: c# event-handling thread-safety dispose

在之前的一个问题中,我遇到了一个很棒的解决方案来解决我遇到的内存泄漏问题。但是有一个问题 - 解决方案涉及在事件处理程序中处理不必要的数据,该事件处理程序似乎在最后一次迭代完成之前被调用。每次从我的网络摄像头中拉出新帧时,它都会调用此事件处理程序。

    private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
    {
        //textBox1.Text = "Frame #: " + counter;
        //counter++;

        //bitmap = (Bitmap)eventArgs.Frame.Clone();
        if (bitmap != null)
            bitmap.Dispose();
        bitmap = new Bitmap(eventArgs.Frame);

        //bitmap = AForge.Imaging.Image.Clone(eventArgs.Frame);


        if (videoPictureBox1.Image != null)
            videoPictureBox1.Dispose(); //THE CRASH HAPPENS HERE. 
        videoPictureBox1.Image = bitmap;
    }

错误是:跨线程操作无效:控制从其创建的线程以外的线程访问的“videoPictureBox1”。

我的问题是我对C#线程并不熟悉,而且通常不适合使用线程。我在StackOverflow上发现了类似的问题,但没有一个我能够提取足够的与我自己的问题有关的信息让我走上正轨(或者我看起来正确答案而错过了它!)

我在下面的链接中找到了两个MSDN答案,但我仍然有一点困难时间掌握哪个解决方案最适合我的问题。

http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k%28EHInvalidOperation.WinForms.IllegalCrossThreadCall%29;k%28TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5%29;k%28DevLang-csharp%29&rd=true

http://msdn.microsoft.com/en-us/library/8843a9ch.aspx

我很抱歉在如此短的时间内提出了两个问题,也为他们提出了同样的话题。我只是害怕在正确的方向上没有轻推,我可能会像谷歌上的一条鱼一样徘徊一段时间,看着错误的地方。

所以我的问题:您认为哪种方法最适合避免此错误?如果您碰巧知道文档,示例代码或教程可以帮助我解决这个问题,那也太棒了。

谢谢!

1 个答案:

答案 0 :(得分:1)

如果您仍在使用视频图片盒,则不应该将其丢弃。您应该只处理不再需要的资源。

您的代码应该是这样的

private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
    var newBitmap = new Bitmap(eventArgs.Frame);
    //This assumes the picture box descends from Control
    if(videoPictureBox1.InvokeRequired)        
    {
        Action action = () => videoPictureBox1.Image = newBitmap;
        //Invoke to make the action happen on the GUI thread
        videoPictureBox1.Invoke(action);
    }
    else
        videoPictureBox1.Image = newBitmap;    
    //Dispose the old bitmap now that it is not assigned to the picturebox anymore   
    if (bitmap != null)
        bitmap.Dispose();
    bitmap = newBitmap;
}

您还可以将逻辑拆分为另一个方法,然后根据是否需要调用来调用该方法。