Программа не закрывается, а камера 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 у меня нет кода.

Итак, есть ли способы перечислить подпотоки, а затем закрыть их один за другим, если нажать крестик в правом верхнем углу для выхода из приложения?


person user613326    schedule 08.12.2012    source источник


Ответы (8)


Что ж, мне удалось отладить программу и, наконец, найти причину проблемы. Это немного странно, потому что в качестве кнопки я мог остановить камеру с помощью функции 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;
 } 

Я все еще немного смущен, почему это не сработает в случае закрытия. Но вроде бы этим решается.

person user613326    schedule 10.12.2012
comment
Я только что столкнулся с такой же ситуацией, и мне кажется, что очень важно, из какого потока вызывается WaitForStop (). Теперь я выполняю все ожидания в отдельном потоке, и он отлично работает. - person Xan-Kun Clark-Davis; 16.03.2017

Возможно, у вас возникли проблемы с утечкой памяти, вызванные событием. Вы можете попробовать отключить событие при выходе из программы:

FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame);

Может это поможет.

person 0__1    schedule 08.12.2012
comment
немного помогло, сейчас реже случается, но все равно бывает. как будто какая-то часть все еще продолжается, а остальная часть приложения остановлена, - person user613326; 10.12.2012

Это помогло с другой проблемой, когда я хотел показать предварительный просмотр, щелкнуть кнопку «захватить», изменить разрешение камеры с низкого разрешения на высокое, захватить изображение, а затем вернуться к низкому разрешению для предварительного просмотра. Вот что сработало, хотя мне пришлось отказаться от этого, потому что остановка и запуск камеры сбрасывали автоматическую экспозицию, поэтому изображение на захваченном изображении было ужасным:

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. Я надеялся использовать OpenCV.NET или просто обычный .NET API с DirectShow или WIA, но это был самый простой вариант, и он сработал для меня.

А вот несколько хороших примеров, которые было трудно найти, но очень полезные: https://github.com/mdavid/aforge.net

person Brian C    schedule 18.09.2014

Я занимался этой проблемой. Вот простой способ остановить камеру и закрыть Win Form.

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

В моей ситуации был нужен 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% случаев. Иногда вызов com-объекта (mediaControl.Stop ();) в методе WorkerThread () просто длился вечно.

person Sebastiano    schedule 13.06.2017

Избегайте прямого взаимодействия с формой - надейтесь на лучшее решение, чем таймер, но решает проблему. я

Статический вспомогательный класс

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();
        }
    }
person Gowldev    schedule 26.01.2019

Это уничтожит вашу проблему (у меня была эта проблема, я пробовал)

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
        }
 }
person user10533354    schedule 27.03.2019

Я пробовал какое-то решение, но ничего не работает. Я частично решил добавить поток сна после WaitForStop

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

если я попытаюсь вызвать Stop, приложение зависнет

person elle0087    schedule 23.09.2020