AForge.NET

  :: AForge.NET Framework :: Articles :: Forums ::

WaitForStop() never returns

Forum to discuss AForge.NET Framework, its features, API, how-tos, etc.

WaitForStop() never returns

Postby BPlagens » Mon Sep 02, 2019 12:08 pm

Hello,
i have a problem with the WaitForStop() function.
In debug mode with single-step it always work. But without break-point sometimes the function never returns.
I spend hours with trying different tipps found with google - but still no success.

For debugging i added a few "Debug.Print" into the WaitForStop function in VideoCaptureDevice.cs:
Code: Select all
        public void WaitForStop( )
        {
            if ( thread != null )
            {
                Debug.Print("WaitForStop thread != null");
                // wait for thread stop
                thread.Join( );
                Debug.Print("WaitForStop thread joined!");
                Free( );
                Debug.Print("WaitForStop Free -> ok");
            }
        }


A typical output is like this:
WaitForStop thread != null
WaitForStop thread joined!
WaitForStop Free -> ok
WaitForStop thread != null
WaitForStop thread joined!
WaitForStop Free -> ok
WaitForStop thread != null
- here is the "joined" and " Free ok" missing

When the function did not return and i press the pause-button on ide and change to the right thread the IDE shows me as next line 1255 from WorkerThread of VideoCaptureDevice.cs:

Code: Select all
mediaControl.Stop( );



This is my CloseVideoSource function:
Code: Select all
private void CloseVideoSource()
        {
            //if (camDevices != null && camDevices.Current.IsRunning)
            //{
            //    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate
            //    {
            camDevices.Current.SignalToStop();
            camDevices.Current.WaitForStop();
            camDevices.Current.NewFrame -= Current_NewFrame;
            camDevices = null;
            //}, null);
            //}
        }



Can anyone of you please have a look at my Source - where is my failure?
Thank you very much!

BR Bernd

Here my full code:
Code: Select all
using System;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Diagnostics;

using AForge.Video;
using AForge.Video.DirectShow;

using System.Drawing;
using System.Drawing.Imaging;

namespace WebCamTest
{

    public partial class MainWindow : Window
    {
        public int bestindex = 0;
        public int viewindex = 0;
        public bool takeSnapshot = false;
        public bool okSnapshot = false;

        public Bitmap myTestBitmap;
        public CameraDevices camDevices;
        public VideoCapabilities[] videoCapabilities;

        public MainWindow()
        {
            InitializeComponent();
            BT_Connect.IsEnabled = true;
            BT_DisConnect.IsEnabled = false;
            BT_SnapShot.IsEnabled = false;
        }

        private void BT_Connect_Click(object sender, RoutedEventArgs e)
        {
            InitWebCam(false);
            BT_Connect.IsEnabled = false;
            BT_DisConnect.IsEnabled = true;
            BT_SnapShot.IsEnabled = true;
        }

        private void BT_DisConnect_Click(object sender, RoutedEventArgs e)
        {
            CloseVideoSource();
            BT_Connect.IsEnabled = true;
            BT_DisConnect.IsEnabled = false;
            BT_SnapShot.IsEnabled = false;
        }

        private void BT_SnapShot_Click(object sender, RoutedEventArgs e)
        {
            CloseVideoSource();
            InitWebCam(true);
            BT_Connect.IsEnabled = false;
            BT_DisConnect.IsEnabled = true;
            BT_SnapShot.IsEnabled = true;
        }

        public void InitWebCam(bool highRes)
        {
            if (camDevices != null)
            {
                if (camDevices.Current != null)
                {
                    CloseVideoSource();
                }
            }

            camDevices = new CameraDevices();

            int CamNumber = 0;
            camDevices.SelectCamera(CamNumber);
            videoCapabilities = camDevices.videoCapabilities;
           
            //search preview and best resolution
            int index = 0;
            int oldwidth = 0;
            if (!highRes)
            {
                foreach (VideoCapabilities capabilty in videoCapabilities)
                {
                    if (capabilty.FrameSize.Width == 640)
                    {
                        viewindex = index;
                    }

                    if (capabilty.FrameSize.Width >= oldwidth)
                    {
                        oldwidth = capabilty.FrameSize.Width;
                        bestindex = index;
                    }
                    index++;
                }
            }

            //switch to preview or screenshot resolution
            if (highRes)
            {
                camDevices.Current.VideoResolution = videoCapabilities[bestindex];
            }
            else
            {
                camDevices.Current.VideoResolution = videoCapabilities[viewindex];
            }

            camDevices.Current.NewFrame += Current_NewFrame;
            camDevices.Current.Start();
        }

        private void Current_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            try
            {
                ShowFrame((Bitmap)eventArgs.Frame.Clone());
            }
            catch (ObjectDisposedException)
            {
                // not sure, why....
            }
        }

        private void ShowFrame(Bitmap frame)
        {

            var bitmapSource = CreateBitmapSourceFromGdiBitmap(frame);

            if (takeSnapshot)
            {
                takeSnapshot = false;
                myTestBitmap = new Bitmap(frame);

                //SaveWebCamSnapshot();
                okSnapshot = true;
                frame.Dispose();
                bitmapSource = null;
                Debug.Print(DateTime.Now.ToString("HH:mm:ss.fff") + " new frame end after screenshot");
                return;
            }

            frame.Dispose();
            bitmapSource.Freeze();

            this.Dispatcher.Invoke(() =>
            {
                try
                {
                    imgViewer.Source = bitmapSource;
                }
                catch (Exception e)
                {
                    Debug.Print(e.ToString());
                }
            });

            bitmapSource = null;
        }

        private void CloseVideoSource()
        {
            //if (camDevices != null && camDevices.Current.IsRunning)
            //{
            //    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate
            //    {
            camDevices.Current.SignalToStop();
            camDevices.Current.WaitForStop();
            camDevices.Current.NewFrame -= Current_NewFrame;
            camDevices = null;
            //}, null);
            //}
        }

        public static BitmapSource CreateBitmapSourceFromGdiBitmap(Bitmap bitmap)
        {
            if (bitmap == null)
                throw new ArgumentNullException("bitmap");

            var rect = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height);

            var bitmapData = bitmap.LockBits(
                rect,
                ImageLockMode.ReadWrite,
                System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            try
            {
                var size = (rect.Width * rect.Height) * 4;

                return BitmapSource.Create(
                    bitmap.Width,
                    bitmap.Height,
                    bitmap.HorizontalResolution,
                    bitmap.VerticalResolution,
                    System.Windows.Media.PixelFormats.Bgra32,
                    null,
                    bitmapData.Scan0,
                    size,
                    bitmapData.Stride);
            }
            finally
            {
                bitmap.UnlockBits(bitmapData);
            }
        }
    }

    public class CameraDevices
    {
        public FilterInfoCollection Devices { get; private set; }
        public VideoCaptureDevice Current { get; private set; }
        public VideoCapabilities[] videoCapabilities;

        public CameraDevices()
        {
            Devices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
        }

        public void SelectCamera(int index)
        {
            if (index >= Devices.Count)
            {
                throw new ArgumentOutOfRangeException("index");
            }
            Current = new VideoCaptureDevice(Devices[index].MonikerString);
            videoCapabilities = Current.VideoCapabilities;
        }
    }
}
BPlagens
 
Posts: 2
Joined: Mon Sep 02, 2019 11:29 am

Re: WaitForStop() never returns

Postby andrew.kirillov » Mon Sep 02, 2019 1:11 pm

Hello,

Run in Debug mode, click Stop button and reproduce the issue - when WaitForStop() does not return. Now pause debugging in Visual Studio and check what your threads area doing. You may find where they get blocked.

Here is why you get the issue. UI thread handles Stop button. It sends signal to Camera thread to stop and waits for it. However, your Camera thread just got new frame and fired NewFrame event. In your ShowFrame() function you call Invoke() to get into UI thread - this where you get blocked as UI thread is currently handling your Stop button. So Invoke() never returns, ShowFrame() never return, NewFrame event handler never returns and so video source’s thread never stops.

Try using AsyncVideoSource around your video source. It may help. I hope.
With best regards,
Andrew


Interested in supporting AForge.NET Framework?
User avatar
andrew.kirillov
Site Admin, AForge.NET Developer
 
Posts: 3453
Joined: Fri Jan 23, 2009 9:12 am
Location: UK

Re: WaitForStop() never returns

Postby BPlagens » Tue Sep 03, 2019 7:14 am

Hello Andrew,

thank you for your quick reply! :-)

Your tip was unfortunately not successful i still get the same error.
I am a novice in multithreading so it is not a easy task for me, but i still try to find a way...

I will be back when i have working solution.

Best Regards, Bernd
BPlagens
 
Posts: 2
Joined: Mon Sep 02, 2019 11:29 am

Re: WaitForStop() never returns

Postby andrew.kirillov » Tue Sep 03, 2019 7:37 am

Try setting SkipFramesIfBusy property of AsyncVideoSource to true.
With best regards,
Andrew


Interested in supporting AForge.NET Framework?
User avatar
andrew.kirillov
Site Admin, AForge.NET Developer
 
Posts: 3453
Joined: Fri Jan 23, 2009 9:12 am
Location: UK




Return to AForge.NET Framework