简体   繁体   中英

How to stop event-handler?

To show the live-stream of a camera an event-handler is started. The code for this event is:

       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();
    }

Now, when I close the camera (see code below), it gives me an error-message "Thread was interrupted from a waiting state." back and the debugger jumps to the Dispatcher.Invoke-Code (see above).

When I uncomment the MessageBox.Show("0"), the error is NOT shown anymore and everything works fine after pressing the OK-Button of this messagebox.

This is the code for closing the camera and the event-handler:

             // 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();

Does someone knows what I am doing wrong and how to avoid such error-message (without the messagebox)?

Thanks!


UPDATED Code

These steps are performed:

1) Camera is opened and the onFrameEventFocusCam event-handler is called

2) The image is valid and shown on the GUI

3) In the Main UI the camera is closed again and the event disabled

4) For some reasons (race-condition?) the same event is re-activated again

This is the part of the main-thread where the camera is closed again:

    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.. 

After the "}" the following event is reactivated again and it jumps again to the 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();
    }

What's happening is that while your program is executing the "close camera" code, the camera has raised an event, causing the Dispatcher.Invoke() method to be called, thus causing the event-raising thread to wait until the UI thread can process the invoked method.

Presumably you are executing the "close camera" code in the UI thread (eg in response to a user input, like a button click or something). This means that event-raising thread cannot proceed until you're done with the "close camera" code. But the last thing that code does is call Camera.Exit() . This apparently causes the camera library to interrupt the event-raising thread which was waiting, causing the exception.

The exception goes away when you call MessageBox.Show() , because that causes the Dispatcher to pump window messages, including the one that processes the invoked method for your call to Dispatcher.Invoke() . This unblocks the event handler, letting it return before you get to the point of calling Camera.Exit() , avoiding the need for the camera library to interrupt the thread.

I think the simplest way to fix it in this case is simply to call Dispatcher.BeginInvoke() (or the newer Dispatcher.InvokeAsync() ) method. That will cause the method invocation to be queued asynchronously, allowing the event handler to return immediately without waiting on the UI thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM