8

少し奇妙な問題があり、デバッグが難しいことがあります。プログラムを閉じることができず、閉じようとするとフリーズすることがあります。

私はビデオ画像認識のための大きなプログラムを作りました。カメラを閉じるための特別なボタンを作りました。このボタンは、以下の関数を呼び出すことでこれと連動し、実際に機能します。

 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から私はコードを持っていません。

では、サブスレッドを一覧表示してから1つずつ閉じる方法はありますか?上隅の右十字を押してアプリケーションを終了する場合はどうでしょうか。

4

9 に答える 9

13

さて、私はなんとかプログラムをデバッグし、最終的に問題の原因を見つけました。ボタンとして機能を使ってカメラを止めることができたので少し不思議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;
 } 

私はまだそれについて少し混乱しています、なぜこれがクロージングイベントの場合に機能しないのですか?しかし、これで解決したようです。

于 2012-12-10T13:53:03.597 に答える
3

イベントが原因でメモリリークの問題が発生している可能性があります。プログラムを終了するときに、イベントのフックを解除してみてください。

FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame);

多分これは役立つでしょう。

于 2012-12-08T19:33:47.513 に答える
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;
    }

}

もう1つ言及すべきことは、AForgeライブラリは、Windows 8メトロアプリの世界を掘り下げることなく、Webカメラを使用して静止画像を取得してJPEGとして保存するために見つけた最も一貫した方法でした。私はOpenCV.NET、またはDirectShowまたはWIAで通常の.NET APIを使用することを望んでいましたが、これは最も単純で、私にとってはうまくいきました。

そして、ここに見つけるのは難しいが非常に有用ないくつかの良いサンプルがあります: https ://github.com/mdavid/aforge.net

于 2014-09-18T06:35:17.880 に答える
0

私はこの問題に取り組んでいました。カメラを停止してWinFormを閉じる簡単な方法は次のとおりです。

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (FinalVideo != null)
    {
        if (FinalVideo.IsRunning)
        {
            FinalVideo.SignalToStop();
            FinalVideo = null;
        }
    }
}
于 2017-02-08T14:52:45.167 に答える
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();)の呼び出しが永遠にかかることがありました。

于 2017-06-13T14:40:45.013 に答える
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();
        }
    }
于 2019-01-26T04:02:49.060 に答える
0

これはあなたの問題を破壊します(私はこの問題を抱えていました、私は試しました)

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
        }
 }
于 2019-03-27T20:48:49.943 に答える
0

これはあなたが必要とするものであり、100%機能するソリューションです:

private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
    Invoke((MethodInvoker) delegate
    {
        _videoSource.SignalToStop();
        _videoSource.WaitForStop();
    });
}
于 2021-08-29T21:00:00.620 に答える
-1

私はいくつかの解決策を試しましたが、何も機能しません。WaitForStopの後にスレッドスリープを追加することを部分的に解決しました

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

停止アプリケーションを呼び出そうとするとフリーズします

于 2020-09-23T10:48:55.383 に答える