2012-05-02 22 views
5

私はC#でiOSプロジェクトを作成しています。プログラムは、接続されたウェブカメラから画像をキャプチャし、それをソケット経由でiPhone/iPadに送信します。これはすべて正常に動作し、私は正常にストリームをデバイス上に表示させることができます。Dispose()を呼び出した後にプログラムがハングする

クライアントとの接続が切断されると、ウェブカメラをオフにする必要があります。この機能では、プログラムがハングアップするだけです。エラーメッセージも例外呼び出しもありません。ちょうどハングします!私はそれが複数のスレッドの問題だと思いますが、残念ながら私は解決策を見つけるためにC#で経験はありません。私はここで誰かが右のトラックに私を持って来ることを願って...

コード:
onImageCaptured機能:

このCameraクラスのように定義され
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()が呼び出されます。これまでのところうまく動作します! Now:

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 function()内で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

Webカムをオフにするためのコードを記述するためのイベントが存在する可能性があります。コントロールで利用可能なイベントリストを確認できますか? – MACMAN

+0

私が気づいたのは、Cameraクラスに 'void Dispose()'という関数があります。このボタンを使ってカメラを回すと、この方法は起動しません。クライアントが切断すると、この処分関数 – Pascal

3

本当にコメントか回答が必要かどうかわかりませんが、少なくとも私はあなたを正しい道に導くことができます。

I found the sourceを使用しているライブラリに追加します。これはここに、そこCamera.Dispose()

public void Dispose() 
{ 
    StopCapture(); 
} 

[OK]を、ではない多くの助けの内容で再び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#の相互運用機能とより多くの経験を持っている誰がこれを編集して、問題をデバッグするために、次をどうするかのより多くを追加したい場合は、コミュニティのwiki作っています。

+0

あなたの答えはThx。確かにどこかで壊れていますが、これは私の視覚的なC# - C++レベルを上回る解決策です。私はdirectShowを使用しない別のウェブカメラスクリプトを探す必要があると思います。 – Pascal

0

、屋がそうしたい場合にもTouchless.CurrentCamera.Disposeを追加することができますカメラから切断するTouchless.RefreshCameraListを使用してください。未管理コードのデバッグを有効にする必要があります

関連する問題