2012-12-08 15 views
4

디버깅하기가 어렵다고 생각되는 조금 이상한 문제가 있습니다. 때때로 프로그램을 닫을 수 없으며 프로그램을 닫을 때 멈출 수 있습니다. 큰 프로그램을 만들었습니다. 비디오 이미지 인식, 작동합니다. 카메라를 닫으려고 특수 버튼을 만들었습니다. 이 버튼은 아래 함수를 호출하여 작동하며 실제로 작동합니다.프로그램이 닫히지 않고 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(); 
} 

내 문제 솔기처럼 시작되었다 (그리고 이것은 내가이 순간을 디버깅 cannt 때문에 추측입니다) 어떤 스레드가 계속 업데이트하고 싶은 활성화되어 있는지 것을 데이터가있는 기본 양식. 그러나 닫을 수 있기 때문에 그렇게 할 수 없습니다. 나는 그런 일이 벌어지고 생각은 그래서 난 주 응용 프로그램 형태로 프로그램이 종료 더 많은 문제를 가지고 장소에서 마지막 코드 그러나

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

에 썼다?

나는 subthreads 출구를 보내고 싶다. 그러나 나는 그들의 이름을 알고있다. (만약 그들이 이름을 가지고 있다면) 나는 그들을 나열하는 법을 모른다. 코드. 일부 DLL에서 코드가 없습니다.

하위 스레드를 나열한 다음 하나씩 종료하는 방법이 있습니다. 응용 프로그램을 종료하기 위해 uppercorner 오른쪽 십자가를 누르는 방법이 있습니까?

답변

8

글쎄 나는 프로그램을 디버깅 할 수 있었고 결국 문제의 원인을 발견했다. 버튼으로 exitcamera 함수를 사용하여 카메라를 멈출 수 있기 때문에 약간 이상합니다.

그러나 _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; 
} 

저는 여전히 약간 혼란 스럽습니다. 닫는 이벤트에서 작동하지 않습니다. 그러나 이것으로 해결할 솔기가 있습니다.

+0

방금 ​​동일한 상황이 발생하여 WaitForStop()이 호출 된 스레드에서 매우 중요하다고 생각됩니다. 이제는 모든 대기를 별도의 스레드에서 수행하며 완벽하게 작동합니다. –

3

아마도 이벤트로 인한 메모리 누수 문제가있을 수 있습니다. 당신은 프로그램을 종료하는 동안 이벤트를 unhook하려고 할 수 있습니다 :

FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame); 

아마도 이것이 도움이 될 것입니다.

+0

조금 도움이되었지만 지금은 거의 발생하지 않지만 여전히 발생합니다. 마치 응용 프로그램의 나머지 부분이 멈추는 동안 어떤 부분이 계속 진행되는 것처럼 보입니다. – user613326

0

미리보기를 표시하고 "잡아"버튼을 클릭하고 카메라의 해상도를 고해상도에서 고해상도로 변경하고 이미지를 잡고 다시 저해상도로 변경하려고 할 때 다른 도움이되었습니다. 시사. AForge 라이브러리는 ...

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

} 

또 한가지 언급하기 : 여기 사진이 캡처 한 이미지 끔찍 했어, 그래서 카메라를 중지하고 시작하면 자동 노출을 재설정하기 때문에 그것을 포기했다하더라도 일 것입니다 웹캠을 사용하여 정지 이미지를 캡처하고 Windows 8 메트로 응용 프로그램의 세계를 탐색하지 않고도 JPEG로 저장할 수 있었던 가장 일관된 방식이었습니다. OpenCV.NET을 사용하거나 DirectShow 나 WIA를 사용하는 일반 .NET API를 사용하기를 바랬지 만 이것이 가장 간단하고 저에게 효과적이었습니다.나는이 문제를 처리했다 https://github.com/mdavid/aforge.net

0

:

그리고 여기 찾기가 강하고 매우 유용했다 좋은 샘플입니다. 다음은 카메라를 멈추고 Win Form을 닫는 간단한 방법입니다.

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

제 상황에서는 WaitForStop()이 필요했지만 코드 실행이 메서드 내에서 종료되었습니다. 내가 함께 오른쪽 SignalToStop()에 대한 호출 후 교체했습니다

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

편집 :이 걸림 해결되지 않았다

while (m_Device.IsRunning) { } 

이것은 AForge 라이브러리에 포함 된 코드입니다 시대의 100 %. 때때로 WorkerThread() 메서드의 com 객체 (mediaControl.Stop();)에 대한 호출이 영원히 걸렸습니다.

관련 문제