10

I have a bit strange problem, which I find hard to debug Sometimes I can't close my program and it freezes when I try to close it.

I made a large program for video image recognition. I made a special button to close the camera. This button works with this by calling a function below, and it indeed, it does work.

 private void exitcamera()
 { 
 FinalVideo.SignalToStop();
 FinalVideo.WaitForStop();
 FinalVideo = null;
 }

Notice that the original video was started like this

 private void buttonStartCamera_Click(object sender, EventArgs e) 
 {
 FinalVideo = new VideoCaptureDevice(VideoCaptureDevices[comboBox1.SelectedIndex].MonikerString);
 FinalVideo.DesiredFrameSize = new System.Drawing.Size(640, 480);
 FinalVideo.DesiredFrameRate = 90;
 FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
 FinalVideo.ProvideSnapshots = true;  //snapshots
 FinalVideo.Start(); 
 }

Now my problem seems (and this is a guess because I can't debug this moment) That some thread is still active wanting to update the main form with data. However it might not be able to do so since that one is closing. I think something like that is going on so I wrote on the main application form

    private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    {
     // Thread.Sleep(1000); // not sure about these delays might help syncing threads
     ExitCamera();
     Thread.Sleep(1000);
    }

However with that last code in place the program has even more trouble to exit.

I would like to send the subthreads an exit, but I dont know their names (if they have a name), I dont know how to list them or to instruct them to stop they are in another dll not my part of the code. From some dll's I dont have the code.

So are there ways of listing sub threads and then close them one by one, if one presses the uppercorner right cross to exit the application?

MackM
  • 2,906
  • 5
  • 31
  • 45
user613326
  • 2,140
  • 9
  • 34
  • 63

10 Answers10

13

Well I managed to debug the program, and finally found what caused the problem. It is a little bit strange since as a button I could stop the camera using the exitcamera function.

However, inside a _formclosing event the same routine didn't work although it worked after I had marked out the waitforstop function.

 private void exitcamera()
 { 
  FinalVideo.SignalToStop();
  // FinalVideo.WaitForStop();  << marking out that one solved it
  FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame); // as sugested
  FinalVideo = null;
 } 

I am still a bit confused about it, why this wont work in case a closing event. But it seems to be solved by this.

halfer
  • 19,824
  • 17
  • 99
  • 186
user613326
  • 2,140
  • 9
  • 34
  • 63
  • 1
    I just encountered the same situation and it seems to me, that it is very important from which thread the WaitForStop() is called. I now do all the waiting in a seperate thread and it works perfectly. – Xan-Kun Clark-Davis Mar 15 '17 at 22:01
4

Maybe you have memory leaks problems caused by the event. You could try to unhook the event while exiting the programm :

FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame);

Maybe this will help.

  • it did help a bit, it now happens less often, but it still happens. as if some part still goes on while the rest of the application is stopped, its puzling – user613326 Dec 10 '12 at 10:57
1

This helped with another problem when I wanted to show a preview, click a "grab" button, change the resolution of the camera from low res to high res, grab an image, and then change back to low res for the preview. Here is what worked, even though I had to abandon it because stopping and starting the camera reset the auto exposure so the picture was awful on the grabbed image:

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

public partial class Form1 : Form

{
    private int PreviewRefreshDelayMS = 40;
    private FilterInfoCollection VideoCaptureDevices;

    private VideoCaptureDevice CustomerWebcam;
    private int CustomerWebcam_CapabilitiesIndexMin;
    private int CustomerWebcam_CapabilitiesIndexMax;
    private bool bCustomerWebcam_capture;
    private Bitmap CustomerWebcam_bitmap;
    private System.DateTime CustomerWebcam_nextframetime = DateTime.Now;

    public Form1()
    {
        InitializeComponent();
    }

    // Some good info to make this more robust
    // http://haryoktav.wordpress.com/2009/03/21/webcam-in-c-aforgenet/
    //
    private void button1_Click(object sender, EventArgs e)
    {            
        CustomerWebcam = new VideoCaptureDevice(VideoCaptureDevices[comboBox1.SelectedIndex].MonikerString);
        CustomerWebcam.NewFrame += new NewFrameEventHandler(CustomerWebcam_NewFrame);

        int indexMin = -1;
        int MinPixels = 0;
        int indexMax = -1;
        int MaxPixels = 0;
        for (int i = 0; i < CustomerWebcam.VideoCapabilities.Length; i++)
        {
            int pixels = CustomerWebcam.VideoCapabilities[i].FrameSize.Height * CustomerWebcam.VideoCapabilities[i].FrameSize.Width; 
            if (indexMin == -1) { indexMin = i; MinPixels = pixels; }
            if (indexMax == -1) { indexMax = i; MaxPixels = pixels; }
            if (pixels < MinPixels) { indexMin = i; MinPixels = pixels; }
            if (pixels > MaxPixels) { indexMax = i; MaxPixels = pixels; }
        }
        CustomerWebcam_CapabilitiesIndexMin = indexMin;
        CustomerWebcam_CapabilitiesIndexMax = indexMax;

        CustomerWebcam.VideoResolution = CustomerWebcam.VideoCapabilities[indexMin];
        CustomerWebcam.DisplayPropertyPage(IntPtr.Zero);
        CustomerWebcam.Start();
    }

   void CustomerWebcam_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        if (CustomerWebcam_bitmap != null)
        { 
            CustomerWebcam_bitmap.Dispose();
            CustomerWebcam_bitmap = null;
        }

        if (bCustomerWebcam_capture)
        {
            CustomerWebcam_bitmap = (Bitmap)eventArgs.Frame.Clone(); 
            System.Random rnd = new Random();
            CustomerWebcam_bitmap.Save("img" + Convert.ToString((int)(rnd.NextDouble() * 10000000)) + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
            bCustomerWebcam_capture = false;
            ((Bitmap)eventArgs.Frame).Dispose();
        }
        else
            if (DateTime.Now > CustomerWebcam_nextframetime)
        {
            CustomerWebcam_bitmap = (Bitmap)eventArgs.Frame.Clone();
            pictureBox1.Image = CustomerWebcam_bitmap;
            CustomerWebcam_nextframetime = DateTime.Now.AddMilliseconds(PreviewRefreshDelayMS);
            ((Bitmap)eventArgs.Frame).Dispose();
        }          
    }       


    private void Form1_Load(object sender, EventArgs e)
    {
        VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
        foreach (FilterInfo VideoCaptureDevice in VideoCaptureDevices)
        {
            comboBox1.Items.Add(VideoCaptureDevice.Name);
        }
        comboBox1.SelectedIndex = 0;
    }

    private void button2_Click(object sender, EventArgs e)
    {
        CustomerWebcam.SignalToStop();
        CustomerWebcam = null;
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (!(CustomerWebcam == null))
            if (CustomerWebcam.IsRunning)
            {
                CustomerWebcam.SignalToStop();
                CustomerWebcam = null;
            }
    }

    private void button4_Click(object sender, EventArgs e)
    {
        bCustomerWebcam_capture = true;
    }

}

One other thing to mention ... the AForge library was the most consistent way I was able to find for using a webcam to grab a still image and save as a JPEG without delving into the world of Windows 8 metro apps. I was hoping to use OpenCV.NET, or just the regular .NET API with DirectShow or WIA, but this was the most simple and it worked for me.

And here are some good samples that were hard to find but very useful: https://github.com/mdavid/aforge.net

Brian C
  • 11
  • 2
0

I was dealing with this problem. Here is a simple way to stop the camera and close Win Form.

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (FinalVideo != null)
    {
        if (FinalVideo.IsRunning)
        {
            FinalVideo.SignalToStop();
            FinalVideo = null;
        }
    }
}
user225045
  • 1
  • 1
  • 3
0

In my situation WaitForStop() was needed, but the code execution was deading inside the method. I've replaced it right after the call to SignalToStop(), with:

while (m_Device.IsRunning) { }

This is the code involved on the AForge library:

public bool IsRunning
{
    get
    {
        if (this.thread != null)
        {
            if (!this.thread.Join(0))
            {
                return true;
            }
            this.Free();
        }
        return false;
    }
}

public void WaitForStop()
{
    if (this.thread != null)
    {
        this.thread.Join();
        this.Free();
    }
}

Edit: this didn't fix the hang the 100% of times. Sometimes a call to a com object (mediaControl.Stop();) on the WorkerThread() method just took forever.

Sebastiano
  • 1,682
  • 2
  • 13
  • 13
0

Avoid direct interaction with the form - hope to have a better solution than timer but solves problem. I

Static helper class

public static Bitmap StaticBitmap = new Bitmap(100,100);

Form

public void Cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {

        lock (StaticHelper.StaticBitmap)
        {
            using (Bitmap b = (Bitmap)eventArgs.Frame)
            {
                StaticHelper.StaticBitmap = (Bitmap)b.Clone();
            }

        }

    }

private void timer1_Tick(object sender, EventArgs e)
    {
        lock (StaticHelper.StaticBitmap)
        {
            pictureBox1.Image = (Bitmap)StaticHelper.StaticBitmap.Clone();
        }
    }
shizhen
  • 12,251
  • 9
  • 52
  • 88
0

This will destroy your problem ( I have had this problem, i tried)

using System.Threading;

bool photo_was_taken = false;


private void buttonStartCamera_Click(object sender, EventArgs e) 
 {

Thread thread = new Thread(new ThreadStart(exitcamera));
thread.Start(); 
 FinalVideo = new VideoCaptureDevice(VideoCaptureDevices[comboBox1.SelectedIndex].MonikerString);
 FinalVideo.DesiredFrameSize = new System.Drawing.Size(640, 480);
 FinalVideo.DesiredFrameRate = 90;
 FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
 FinalVideo.ProvideSnapshots = true;  //snapshots
 FinalVideo.Start(); 
 }
private void FinalVideo_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        // what you want to do ( your code is here )
        photo_was_taken = true; 

    }
 private void exitcamera()
 { 
        while (!photo_was_taken)
        {
            Thread.Sleep(5); // you can change wait milliseconds
        }
        FinalVideo.SignalToStop();
        FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame);
        //FinalVideo.WaitForStop();
        while (FinalVideo.IsRunning)
        {
            FinalVideo.Stop();
            // FinalVideo = null; >> // that is not condition
        }
 }
0

This is what you need, 100% working solutions:

private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
    Invoke((MethodInvoker) delegate
    {
        _videoSource.SignalToStop();
        _videoSource.WaitForStop();
    });
}
TimeCoder
  • 175
  • 1
  • 8
0

Please, let me add my working solution on closing a webcam with the wonderful library AForge.NET. It´s a pitty it development has been abandoned.

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
     if (videoCaptureSource != null)
     {
         while (videoCaptureSource.IsRunning) // Perhaps you need to limit the number of iterations
         {
             videoCaptureSource.SignalToStop();
             videoCaptureSource.WaitForStop();
             if (videoSourcePlayer != null)
             {
                 videoSourcePlayer.SignalToStop();
                 videoSourcePlayer.WaitForStop();
                 //videoSourcePlayer.NewFrame -= new NewFrameEventHandler(videoSourcePlayer_NewFrame); // Uncomment this line if you have added an event handler
             }
             Thread.Sleep(3000);
         }
         videoCaptureSource = null;
         videoDevices = null;
         videoSourcePlayer = null;
     }
}

When I only needed the frame attaching an event handler to the VideoCaptureDevice (not the VideoSourcePlayer) I couldn´t stop the video from the VideoCaptureDevice, instead I used an invisible VideoSourcePlayer and stopped it from there.

Ignacio
  • 910
  • 2
  • 12
  • 24
-1

i tried some solution, but nothing work. i partial solved adding a thread sleep after WaitForStop

if (FinalVideo != null)
    {
        if (FinalVideo.IsRunning)
        {
            FinalVideo.SignalToStop();
            Thread.Sleep(1000);
        }
    }

if i try to call Stop application will be freeze

elle0087
  • 840
  • 9
  • 23