程序不会关闭,aforge相机继续运行,引发故障

时间:2012-12-08 17:50:31

标签: c# multithreading aforge

我有一个奇怪的问题,我觉得很难调试 有时我无法关闭我的程序,当我试图关闭它时会冻结。

我制作了一个大型视频图像识别程序。 我做了一个特殊按钮来关闭相机。这个按钮通过调用下面的函数来解决这个问题,它确实可以工作。

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

请注意原始视频是这样开始的

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

现在我的问题似乎(这是猜测,因为我无法调试这一刻) 想要使用数据更新主窗体,某些线程仍处于活动状态。 但是,由于那个正在关闭,它可能无法这样做。 我觉得这样的事情正在发生,所以我在主申请表上写了

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

然而,使用最后一个代码,程序退出时会遇到更多麻烦。

我想发送子线程一个退出,但我不知道他们的名字(如果他们有一个名字),我不知道如何列出他们或指示他们停止他们在另一个dll而不是我的一部分码。从某些dll我没有代码。

那么有没有办法列出子线程然后一个接一个地关闭它们,如果有人按下右上角以退出应用程序?

8 个答案:

答案 0 :(得分:10)

我设法调试程序,最后找到导致问题的原因。 这有点奇怪,因为我可以使用exitcamera功能停止相机。

然而,在a _formclosing事件中,虽然在我标记了waitforstop函数之后它仍然有效,但同样的例程并没有起作用。

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

我仍然对此感到困惑,为什么在关闭事件时这不会起作用。 但它似乎可以解决这个问题。

答案 1 :(得分:3)

可能是因为事件引起的内存泄漏问题。您可以尝试在退出程序时取消挂起事件:

FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame);

也许这会有所帮助。

答案 2 :(得分:0)

这有助于另一个问题,当我想要显示预览,点击“抓取”按钮,将相机的分辨率从低分辨率更改为高分辨率,抓取图像,然后更改回低分辨率以进行预览。这是有效的,即使我不得不放弃它,因为停止和启动相机重置自动曝光,因此图片在抓取的图像上很糟糕:

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

}
另外还有一件事...... AForge库是我能够找到使用网络摄像头抓取静止图像并保存为JPEG而不钻研Windows 8 metro应用程序世界的最一致方式。我希望使用OpenCV.NET,或者只是使用DirectShow或WIA的常规.NET API,但这是最简单的,它对我有用。

以下是一些很难找到但很有用的好样本:https://github.com/mdavid/aforge.net

答案 3 :(得分:0)

我正在处理这个问题。这是一种停止相机并关闭Win Form的简单方法。

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

答案 4 :(得分:0)

在我的情况下,需要WaitForStop(),但代码执行在方法内部消除。 我在调用SignalToStop()之后立即将其替换为:

while (m_Device.IsRunning) { }

这是AForge图书馆所涉及的代码:

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

编辑:这并没有解决100%的问题。有时在WorkerThread()方法上调用com对象(mediaControl.Stop();)只是永远。

答案 5 :(得分:0)

避免与表单直接交互-希望有一个比计时器更好的解决方案,但可以解决问题。我

静态助手类

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

表格

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

答案 6 :(得分:0)

这将消除您的问题(我曾尝试过此问题)

Row old_video_length    video_length_converted   
1   1:54:55             6895     
2   2:26                146  
3   146                 146  

答案 7 :(得分:-1)

我尝试了一些解决方案,但没有任何效果。 我部分解决了在WaitForStop之后添加线程睡眠的问题

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

如果我尝试致电Stop应用程序将被冻结