2012-05-02 4 views
5

C#으로 iOS 프로젝트에서 작업하고 있습니다. 이 프로그램은 연결된 웹캠에서 이미지를 캡처하여 소켓을 통해 iPhone/iPad로 보냅니다. 이 모든 것은 정상적으로 작동하며 장치에서 스트림을 성공적으로 보여줄 수 있습니다.Dispose()를 호출 한 후 프로그램이 중단됩니다.

그러나 클라이언트가 연결을 끊으면 웹캠이 꺼져 야하며이 기능에서는 프로그램이 멈 춥니 다. 오류 메시지도없고 예외 호출도 없습니다 ... 그냥 멈 춥니 다! 여러 스레드에서 문제가 있다고 생각하지만 유감스럽게도 솔루션을 찾기 위해 C#에서 경험하지 못했습니다.
onImageCaptured 기능 : 카메라 클래스에서 다음과 같이 정의

public void OnImageCaptured(Touchless.Vision.Contracts.IFrameSource frameSource, Touchless.Vision.Contracts.Frame frame, double fps) 
{ 
    _latestFrame = frame.Image; 
    Console.WriteLine("OnImageCaptured"); 
    if (isConnected) 
    { 
     Console.WriteLine("OnImageCaptured - isConnected"); 
     byteArray = new byte[0]; 
     MemoryStream stream = new MemoryStream(); 

     _latestFrame.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); 
     stream.Close(); 
     byteArray = stream.ToArray(); 

     if (byteArray.Length > 0) 
     { 
      string eof = "<EOF>"; 
      byte[] eofByte = Encoding.ASCII.GetBytes(eof); 
      Console.WriteLine("OnImageCaptured - sendStream"); 
      this.onDataSend(byteArray); 
      this.onDataSend(eofByte); 
      stream.Flush(); 
     } 

     System.Diagnostics.Debugger.Log(0, "1", "\nByte Array Length: " + byteArray.Length.ToString()); 
    } 
    pictureBoxDisplay.Invalidate(); 
} 

:

public event EventHandler<CameraEventArgs> OnImageCaptured; 

그리고 트리거 : 나는 ... 여기 사람이 바른 길에 저를 가져올 수

코드를 희망

OnImageCaptured.Invoke(this, new CameraEventArgs(bitmap, fps)); 

이 기능 - 내가 생각하는 - 실행 UI를 이후 별도의 위협에서 이미지가 들어오는 경우 차단되지

그래서 클라이언트 단선이 기능으로 처리되어 다음 :.

public void onDataSend(byte[] data) 
{ 
    clientReady = false; 
    try 
    { 
     socketWorker.Send(data); 
    } 
    catch (SocketException se) 
    { 
     isConnected = false; 
     Console.WriteLine("Error: Data Write - SocketException"); 
     Console.WriteLine(se.ErrorCode.ToString()); 
     thrashOldCamera() // THIS FUNCTION HANGS THE PROGRAM !! 
     onDisconnectServer(); 

     // onDisconnectServer(); 
    } 
    catch (ObjectDisposedException) 
    { 
     isConnected = false; 
     Console.WriteLine("Error: Data Write - ObjectDisposedException"); 
     // onDisconnectServer(); 
    } 

} 

클라이언트 연결이 끊어을 thrashOldCamera()가 호출됩니다. 지금까지 잘 작동합니다! 지금 :

private void thrashOldCamera() 
{ 
    Console.WriteLine("TrashOldCamera"); 
    // Trash the old camera 
    if (_frameSource != null) 
    { 
     try 
     { 
      _frameSource.NewFrame -= OnImageCaptured; 
      Console.WriteLine("TrashOldCamera - 1"); 
      _frameSource.Camera.Dispose(); // HERE IT HANGS. IT NEVER GOES PAST HERE !!! 
      Console.WriteLine("TrashOldCamera - 2"); 
      setFrameSource(null); 
      Console.WriteLine("TrashOldCamera - 3"); 
      pictureBoxDisplay.Paint -= new PaintEventHandler(drawLatestImage); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("End Trash Camera Ex: " + ex); 
     } 
    } 
    Console.WriteLine("End Trash Camera"); 
} 

프로그램이 _frameSource.Camera.Dispose();에 있습니다. 위에서 언급했듯이 오류나 예외는 없습니다. onImageCapture 함수() 내에서 onDataReceive()이 호출되는 것이 문제 일 수 있습니다. 또한 thrashOldCamera()을 트리거하는 폼에 버튼을 추가했는데 완벽하게 작동합니다.

어떤 도움이나 힌트라도 진심으로 감사드립니다.

+0

http://channel9.msdn.com/Series/-NET-Debugging-Stater-Kit-for-the-Production-Environment/Diagnosing-Application-Issues-01 –

답변

8

이것은 일반적인 스레드 문제인 교착 상태라고합니다. 교착 상태가 카메라 펌웨어 자체에있을 수 있으므로 사용자가 스 니펫의 어느 위치에서든 UI 스레드에 명시 적으로 호출하는 것을 보지 못합니다. 핵심 문제는 카메라를 닫으려고 시도하는 반면 콜백이 여전히 실행 중이면 그다지 탄력적 인 코드가 많지 않다는 것입니다. Release() 호출은 콜백이 완료 될 때까지 완료 할 수 없습니다. 그러나 Release() 호출이 완료 될 때까지 콜백을 완료 할 수 없습니다. 교착 상태 도시.

코드를 재구성하여 이러한 일이 발생하지 않도록해야합니다. 카메라를 놓는 것을 지연시키는 것이 중요합니다. 카메라를 연 동일한 스레드에서 가장 잘 수행됩니다. 예를 들어 FormClosed 이벤트에서이를 해제하여 해결할 수 있습니다. 아니면 전혀 공개하지 않고 자동으로 핸들을 닫으려면 Windows에 남겨 두십시오. 여전히에 문제가 이런 경우에

0

장치 연결이 끊어져있는 동안 호출 할 이벤트를 찾습니다. 웹캠을 끄는 코드를 작성하십시오.

+0

안녕하세요. 이름 : Gijo, 정확히 무슨 뜻인지 확실하지? – Pascal

+0

웹캠을 끄기위한 코드를 작성하는 데 사용할 수있는 이벤트가있을 수 있습니다. 컨트롤을 통해 사용할 수있는 이벤트 목록을 확인할 수 있습니다. – MACMAN

+0

그래서 방금 알아 챘습니다, 카메라 클래스에 'void Dispose()'라는 함수가 있습니다. 버튼을 사용하여 카메라를 켜면 잘 작동합니다.이 방법은 트리거되지 않습니다. 클라이언트가 연결을 끊으면이 처분 함수가 실행됩니다. – Pascal

3

정말로 이것이 의견이나 답변이되어야하는지 모르겠지만, 적어도 나는 올바른 길로 인도 할 수 있습니다.

I found the source을 사용중인 라이브러리에 저장하십시오. 이 여기에,이 Camera.Dispose()

public void Dispose() 
{ 
    StopCapture(); 
} 

좋아,별로 도움의 내용입니다 다시 Camera.StopCapture()

internal void StopCapture() 
{ 
    _cameraMethods.StopCamera(); 
} 

하나,별로 도움이됩니다. _cameraMethodsCameraMethods이며 직접 쇼와 통신하는 C++ 도우미 라이브러리 인 WebCamLib 라이브러리에서 가져옵니다.

여기 당신의 예외가 관리 경계에 기본 동안 먹게되고 나타납니다 CameraMethods::StopCamera()

void CameraMethods::StopCamera() 
{ 
    if (g_pMediaControl != NULL) 
    { 
     g_pMediaControl->Stop(); 
     g_pMediaControl->Release(); 
     g_pMediaControl = NULL; 
    } 

    g_pfnCaptureCallback = NULL; 

    if (g_pIBaseFilterNullRenderer != NULL) 
    { 
     g_pIBaseFilterNullRenderer->Release(); 
     g_pIBaseFilterNullRenderer = NULL; 
    } 

    if (g_pIBaseFilterSampleGrabber != NULL) 
    { 
     g_pIBaseFilterSampleGrabber->Release(); 
     g_pIBaseFilterSampleGrabber = NULL; 
    } 

    if (g_pIBaseFilterCam != NULL) 
    { 
     g_pIBaseFilterCam->Release(); 
     g_pIBaseFilterCam = NULL; 
    } 

    if (g_pGraphBuilder != NULL) 
    { 
     g_pGraphBuilder->Release(); 
     g_pGraphBuilder = NULL; 
    } 

    if (g_pCaptureGraphBuilder != NULL) 
    { 
     g_pCaptureGraphBuilder->Release(); 
     g_pCaptureGraphBuilder = NULL; 
    } 

    this->activeCameraIndex = -1; 
} 

입니다.이것이 당신에게 얼마나 도움이되는지는 모르겠지만, 적어도 당신에게 어디서부터 볼 지 시작해야합니다.

관리되지 않는 코드 디버깅을 사용하고 라이브러리 소스를 단계별로 실행하여 실제 문제가 어디에 있는지 확인하십시오.

enter image description here

나는이 C++/C#을 interop에 더 많은 경험을 가지고 다른 사람이 편집하고 문제를 디버깅하는 다음 작업을 수행하는 것을 더 추가하고 싶은 경우 커뮤니티 위키 만들고 있어요.

+0

Hello Scott. 당신의 대답은 Thx. 그것은 어딘가에 확실히 파손되어 있지만 이것은 솔루션을 찾기 위해 Visual C# - C++ 레벨 이상의 방법입니다. 나는 directShow를 사용하지 않는 다른 웹캠 스크립트를 찾아야한다고 생각한다. – Pascal

0

, 나중에 그렇게하려는 경우 당신은 또한 Touchless.CurrentCamera.Dispose을 추가 할 수 있습니다 카메라에서 분리합니다 Touchless.RefreshCameraList를 사용합니다. 코드 할 수없는 코드 디버깅을 활성화해야 할 수도 있습니다.

관련 문제