2011-09-08 8 views
7

時々、私の統合テストのいくつかが上記のメッセージで失敗しています。私は以下のコードを使用してポートを準備しています。SerialPort UnauthorizedAccessException

  for(int i = 0; i < 5; i++) 
      { 
       try 
       { 
        port.Open(); 
        if (port.IsOpen) 
         break; 
       } 
       catch (Exception e) 
       { 
        try 
        { 
         port.Close(); 
        } 
        catch (Exception) 
        {} 
        Thread.Sleep(300); 
       } 
      } 

私の仮定のいずれか((それはそれを閉じようとしますので)それがポートをブロックし、現在のスレッドにすることはできませんので、それが適切にクリーンアップせずに死亡した別のスレッドまたはプロセスでなければならないということです他のテスト - このポートには何もアクセスしません)。 SerialPortの状態をリセットして、新しいスレッド/プロセスが再びそのスレッドにアクセスできるようにする方法はありますか?

おかげで、

リチャード

答えて

11

これは、ポート上のイベントを待つために内部ヘルパースレッドを使用して、SERIALPORTクラスの欠陥です。 DataReceivedイベント、PinChangedイベント、およびErrorReceivedイベントのソース。この脆弱性はClose()メソッドの実装にあり、このヘルパースレッドが終了するのを待機しません。それには時間がかかりますが、正確な時間量は予測不可能であり、マシンが特にビジー状態になると数秒かかることがあります。物理ポートは、これが発生するまで閉じられず、スレッドが「既に使用中のポート」例外を持つ爆弾を出る前にポートを開きます。あなたが得るもの。従って、300msecの間スリープすることは十分ではない。

これは通常問題ではありませんが、シリアルポートは共有可能なデバイスではありません。シリアルポートを閉じてプログラムを終了しないことは危険です。別のプロセスがポートを盗む可能性があります。もう一度開こうとすると、この例外が発生します。通常の方法では、アプリケーションの起動時にポートを開き、終了するまでポートを閉じないようにします。

+0

ありがとうHans - これは、異なるテストプロセスが開始されたときのテストでのみ発生します。 –

2

あなたがポートを閉じるどこで見ることができません。

私にとっての問題は、ここでは、ポートが

MSDN

から

つだけ開いている接続はできるまだ開いているときには、おそらくあなたはport.Open();を呼び出している(あなたが少しコードをリファクタリングした場合でも)ではありませんSerialPortオブジェクトごとに存在します。

(なぜ私には十分な情報がないのでわかりません)実際にポートを閉じるには、閉じるメソッドに時間がかかることを覚えておいてください。近くMSDN

から

(おそらくThread.Joinを使用して)されて、任意のアプリケーションのためのベストプラクティスはポートとして、Openメソッドを呼び出そうとする前にCloseメソッドを呼び出した後の時間のいくつかの量を待つことである

すぐに閉じられないことがあります。

詳細は

http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.open.aspx

+0

@Massimilano - あなたの答えに感謝します。ポートはスリープ後にキャッチブロック内で閉じられます(オープンに失敗すると例外がスローされます)。 –

+0

私はそれを見ることができますが、例外がスローされた場合にのみポートを閉じます。 port.Open()が例外をスローしない場合、.Close()は実行されません –

+0

私は明確でない場合は申し訳ありません。オープンが失敗する理由は、スローされているUnauthorizedAccessExceptionが原因です(クローズしようとした理由です)。 –

4

私は、シリアルポートをインスタンス化する直前にポートが閉じていることを定期的に確認します。これは、シリアルポートを閉じずにデバッグコードを停止した場合に役立ちます。また、コードを続行する前にポートを開いたり閉じたりしてから250ミリ秒待つ必要があります。

try 
     { 
      if ((m_SerialPort != null)) 
      { 
       if (m_SerialPort.IsOpen) 
       { 
        m_SerialPort.Close(); 
       } 
      } 
      m_SerialPort = new SerialPort(portName, dataRate, parity, databits, stopBits.One); 
      m_SerialPort.Open(); 
      if (!m_SerialPort.IsOpen) 
      { 
       MessageBox.Show(string.Concat(portName, " failed to open")); 
      } 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
0

GC.SuppressFinalizeGC.ReRegisterForFinalizeはパラメータだけではなく、SERIALPORTインスタンスとしてSERIALPORTインスタンスBaseStreamプロパティを渡して呼び出す必要があります。

関連する問題