如何停止事件处理程序?

时间:2015-01-15 13:14:32

标签: c# multithreading camera event-handling

要显示摄像机的实时流,启动事件处理程序。此事件的代码是:

       private void onFrameEventFocusCam(object sender, EventArgs e)
    {
        uEye.Camera Camera = sender as uEye.Camera;

        Int32 s32MemID;
        Camera.Memory.GetActive(out s32MemID);


        // Read Camera bitmap
        Bitmap bitmap;
        Camera.Memory.ToBitmap(s32MemID, out bitmap);


        Dispatcher.Invoke(new Action(() =>
        {
            // Convert bitmap to WPF-Image
            var bmp = new Bitmap(bitmap);
            var hBitmap = bmp.GetHbitmap();

            System.Windows.Media.ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
            hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

            image_fokus.Source = wpfBitmap;
            image_fokus.Stretch = System.Windows.Media.Stretch.Fill;
            image_fokus.StretchDirection = StretchDirection.Both;

            DeleteObject(hBitmap);
            bitmap.Dispose();

        }));
        GC.Collect();
    }

现在,当我关闭相机时(见下面的代码),它会给我一条错误消息“线程从等待状态中断”。返回,调试器跳转到Dispatcher.Invoke-Code(见上文)。

当我取消注释MessageBox.Show(“0”)时,错误显示为 NOT ,按下此消息框的OK按钮后一切正常。

这是关闭相机和事件处理程序的代码:

             // Close Camera
                Camera.Acquisition.Stop(uEye.Defines.DeviceParameter.Force);                 
                Camera.EventFrame -= onFrameEventFocusCam;              // remove Event

             // MessageBox.Show("0");

                uEye.Defines.Status statusRet = 0;
                statusRet = Camera.Exit();

有人知道我做错了什么以及如何避免这样的错误消息(没有消息框)?

谢谢!


更新代码

执行以下步骤:

1)打开相机并调用 onFrameEventFocusCam 事件处理程序

2)图像有效并显示在GUI

3)在主UI中,相机再次关闭,事件被禁用

4)由于某些原因(竞争条件?),同样的事件再次被重新激活

这是相机再次关闭的主线程的一部分:

    else
    {
      // Close Camera     
      uEye.Defines.Status statusRet = 0;
      statusRet = Camera.Acquisition.Stop(uEye.Defines.DeviceParameter.DontWait);

      Camera.EventFrame -= onFrameEventFocusCam;              // remove Event
      statusRet = Camera.Exit();

    } // end of else.. 

在“}”之后,以下事件再次被重新激活,并再次跳转到onFrameEventFocusCam!

    private void onFrameEventFocusCam(object sender, EventArgs e)
    {
        uEye.Camera Camera = sender as uEye.Camera;

        Int32 s32MemID;
        Camera.Memory.GetActive(out s32MemID);


        // Read Camera bitmap
        Bitmap bitmap;
        Camera.Memory.ToBitmap(s32MemID, out bitmap);


        Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
        {
            // Convert bitmap to WPF-Image
            var bmp = new Bitmap(bitmap);
            var hBitmap = bmp.GetHbitmap();

            System.Windows.Media.ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
            hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

            image_fokus.Source = wpfBitmap;
            image_fokus.Stretch = System.Windows.Media.Stretch.Fill;
            image_fokus.StretchDirection = StretchDirection.Both;

            DeleteObject(hBitmap);
            bitmap.Dispose();

        }));
        GC.Collect();
    }

1 个答案:

答案 0 :(得分:1)

当你的程序正在执行"关闭相机时,会发生什么?代码,摄像头引发了一个事件,导致调用Dispatcher.Invoke()方法,从而导致事件提升线程等待,直到UI线程可以处理被调用的方法。

据推测,您正在执行"关闭相机" UI线程中的代码(例如,响应用户输入,如按钮点击或某事)。这意味着在您使用"关闭相机"完成后,事件提升线程无法继续。码。但代码所做的最后一件事就是调用Camera.Exit()。这显然会导致相机库中断正在等待的事件引发线程,导致异常。

当您致电MessageBox.Show()时,异常就会消失,因为这会导致Dispatcher抽取窗口消息,包括处理调用Dispatcher.Invoke()调用方法的消息。这会取消阻塞事件处理程序,让它在到达调用Camera.Exit()之前返回,从而避免相机库中断线程。

我认为在这种情况下修复它的最简单方法就是调用Dispatcher.BeginInvoke()(或更新的Dispatcher.InvokeAsync())方法。这将导致方法调用异步排队,允许事件处理程序立即返回,而无需等待UI线程。