2

SerialPort クラスでデバイスからデータを取得します。これが私の方法です:

public WriteAndRead(){
    ...
    sp.Write(send_buffer.ToArray(), 0, send_buffer.Count);

    do
        {
            if (sp.BytesToRead > 0)
            {
                ret_val = sp.ReadByte();
                done = true;
            }
            else
                ret_val = -1;
        } while ((!done) && ((Environment.TickCount - char_tmo) < interchar_delay));
    ...
}

だから、他のスレッドから呼び出したい。コードのその部分をlock(sp){}にラップして、読み取りと書き込みを同期させましょうか。または、あるスレッドが書き込み中で、他のスレッドがそれから読み取っている状況をどのように回避できますか?

4

2 に答える 2

1

ロックは仕事をします。ポートを使用している間、別のポートが待機しています。スレッドごと、またはポート プールの種類ごとに個別のポートを使用する場合を除きます。

于 2013-11-03T15:11:18.483 に答える
1

はい、ロックが必要です。Write() 呼び出しは問題なくシリアル化され、デバイス ドライバー内でロックすることによって処理されます。しかし、別のスレッドが最初に sp.Write() を呼び出したスレッドよりも先に競合し、そのスレッドの応答を盗む可能性はゼロではありません。これらのオッズは非常に小さいため、いつレースが行われるかを診断するのは非常に困難です。テスト時にそれを再現することは決してありません.これは週に一度うまくいかないかもしれません.

いいえ、単純でより良い解決策はありません。すべてのデバイス通信を 1 つのスレッドだけに残すこともできますが、個々のスレッドごとに非同期性の問題を解決する必要があります。

コードを修正する必要があります。「interchar_delay」内で応答するデバイスに依存することはできません。遅延はそれよりもはるかに大きく、send_buffer 全体をデバイスで送受信して処理する必要があります。マシンの負荷が高くなると、ガベージ コレクターとオペレーティング システムがプロセスのページをスワップ アウトするため、独自のコードは任意の長い遅延に簡単にさらされる可能性があります。それが Write() 呼び出しの直後に発生すると、災害が発生します。タイムアウトを 10 秒未満にすることは決して考えないでください。それは問題ありません、それは例外的であるはずです。代わりに SerialPort.ReadTimeout プロパティを使用することを強く推奨します。これはドライバーによって実装されており、これらの任意の長い遅延に悩まされることはありません。

于 2013-11-03T16:18:09.930 に答える