0

私はこのフォーラムに初めて参加し、しばらく気になっていた質問があります。私のセットアップは、USB/Uart コンバーターを使用して PC に接続されたシリアル対応のキャラクター ディスプレイです。C++ スタイルの別の書き込みバッファー スレッドで、serialPort クラスを介してディスプレイにバイトを送信しています。

private void transmitThread(){
    while(threadAlive){
        if(q.Count > 0){ // Queue not empty
            byte[] b = q.Dequeue();
            s.Write(b,0,b.Length);
            System.Threading.Thread.Sleep(100);
        }
        else{ // Queue empty
            System.Threading.Thread.Sleep(10);
        }
    }
}

シリアル ポートが既に開いていると仮定すると、これは完全に機能し、すべてのデータがディスプレイに送信されます。ただし、このスニペットには例外処理はまったくありません。したがって、私は典型的な C# 機能である「using」ステートメントを実装し、次のように必要なときにのみポートを開くことを検討していました。

private void transmitThread(){
    while(threadAlive){
        if(q.Count > 0){ // Queue not empty
            byte[] b = q.Dequeue();
            using(s){ //using the serialPort
                s.Open();
                s.Write(b,0,b.Length);
                s.Close();
            }
            System.Threading.Thread.Sleep(100);
        }
        else{ // Queue empty
            System.Threading.Thread.Sleep(10);
        }
    }
}

この関数の問題は、ランダムな量のデータしか送信しないことです。通常、80 バイトのバイト配列の約 3 分の 1 です。スレッドのさまざまな優先度設定を試しましたが、何も変わりません。

重要な何かを見逃しているのでしょうか、それとも送信要求後にポートを閉じるのが速すぎますか?

あなたが私を助けてくれることを願っています。ありがとう :)

4

3 に答える 3

4

いいえ、それは本当に悪い考えでした。うまくいかないことは、大まかに遭遇する順序で:

  • シリアル ポート ドライバーは、ポートを閉じたときにまだ送信されていない送信バッファーに残っているバイトを破棄します。あなたが今見ているものです。

  • SerialPort.Close() に関する MSDN の記事では、ポートを再び開く前に「しばらく待つ」必要があると警告しています。シャットダウンする必要がある内部ワーカー スレッドがあります。待機時間は指定されておらず、マシンの負荷によって異なります。

  • ポートを閉じると、別のプログラムがポートを取得して開くことができます。シリアル ポートは共有できません。もう一度開こうとすると、プログラムが失敗します。

シリアル ポートは、オンザフライで開閉できるようには設計されていません。プログラムの開始時にのみ開き、終了したら閉じます。Close() をまったく呼び出さないことはまったく問題なく、デッドロック シナリオを回避できます。

于 2012-07-17T20:33:01.577 に答える
0

シリアル デバイスの正常な動作が への呼び出しに依存しているThread.Sleep場合、スレッドが何らかの時点で中断され、データ転送がデバイスと同期しなくなる可能性があります。これを解決する方法はおそらくありますが、私が最初に行うことは、代わりに .NET SerialPortクラスを使用することです。Writeメソッドは、やりたいことと非常によく似ており、それらの記事には C++ コードの例があります。

于 2012-07-17T20:31:47.780 に答える
0

using ブロックの要点を見逃していると思います。典型的な using ブロックは次のようになります。

using (var resource = new SomeResource())
{
    resource.DoSomething();
}

オープニングは最初に起こります。通常、コンストラクターの一部として。しかし、時々 using ブロックの最初の行にあります。

しかし、私が見る大きな危険信号は、閉鎖が自動的に行われるということです。.Close()電話は必要ありません。

于 2012-07-17T20:26:17.177 に答える