5

SerialPortクラスとThreadPool.QueueUserWorkItemまたはs Task.

この問題は、2 つ以上の SerialPort を同時に使用した場合にのみ発生します。各シリアル ポートは、次の 3 つの方法のいずれかで作成した独自のスレッドで実行されます。

  1. new Thread(DoSerialCommX)
  2. ThreadPool.QueueUserWorkItem(DoSerialCommX)
  3. new Task(DoSerialCommX, TaskCreationOptions.LongRunning).Start()

この問題を説明するためDoSerialCommXに、ループ内でシリアル ポートの読み取りと書き込みを永続的に行うメソッドを作成しました。次のようになります: (実際のプログラムで実際にこれを行っているわけではありません。これは、問題を切り分けて説明するテスト プログラムからの抜粋です)。

private void DoSerialCommX()
{
    SerialPort port = new SerialPort("ComX", 9600);
    port.Open();

    while(true)
    {
        //Read and write to serial port
    }
}

方法 2 または 3 を使用すると、シリアル通信が途切れ、多くの通信タイムアウトが発生します。方法 1 を使用すれば、すべて問題ありません。また、これは Intel Atom ベースの PC でのみ発生するようです。デスクトップPCは問題ないようです。

スレッド プールがスレッドを再利用し、デフォルトでスレッド プールを使用することは知っていTaskます。そして、スレッドプールが実際には短期間の操作を意図していることを私は知っています。しかしTaskCreationOptions.LongRunning、スレッドプールを使用するのではなく、専用のスレッドを生成すると思われる を使用してみましたが、それでも機能しませんでした。

質問:Threadこの状況で特別な 理由は何ですか? ThreadIO操作により適したものにする何かがありますか?

編集: これまでの回答は、終わりのないプロセスに ThreadPool または Tasks を使用しようとしていると仮定しているようです。私の実際のアプリケーションでは、これは当てはまりません。問題を説明するために、上記のコードで終わりのないループを使用しているだけです。なぜThread機能しThreadPoolTask機能しないのかを本当に知る必要があります。シリアル通信がしゃっくりする原因となる技術的な違いは何ですか?

4

4 に答える 4

2

哲学的には、実行中のスレッドの動作において、1、2、および 3 の間にほとんど違いはありません。オーバーライドしない限り、それらはすべて同じデフォルトの実行優先度を共有します-概念的には、スレッドスケジューラは同じ戦略を使用してそれらをスケジュールします。彼らは皆、輪の中で楽しそうに回転していました。

メソッド間の大きな違いは次のとおりだと思います。

  1. #2 と #3 のスレッドプールをサポートするためにインフラストラクチャ コスト (スレッド、メモリなど) をスピンアップすると、実行ループでクロック タイムスライスが競合します。
  2. 筋肉の少ない Atom でのスレッド コンテキストの切り替えコスト。Atom のキャッシュは小さく、処理パイプラインは短くなります。実行中のスレッドが増えると、コンテキストの切り替えが増え、パイプラインのダンプが増え、命令キャッシュの効率が低下します。

機能的な観点からすると、メソッド 2 と 3 の使用はやや乱用です。意図は、メソッドを決して終了しないことです。これらの戦略は、アトミックで有限な操作に最適化されており、非同期ネットワークやディスク操作などの IO Completion ポート タスクに適したややガイドなしの実行です (シリアル ポート コードにも可能性がありますか?)。

Async IO への適応に興味がない限り、2 と 3 はスキップします。スレッドに焦点を当てる - Threadpool がもたらすインフラストラクチャのオーバーヘッドなしで、よりきめ細かく予測可能な実行制御が必要なようです。

于 2012-04-12T04:28:25.247 に答える
1

コード、ドライバー、またはハードウェアのいずれかに問題があり、シリアルポートのパフォーマンスが「限界」に達しているため、常に機能しなくなる可能性があります。専用スレッドまたはスレッドプールを使用しても問題はないはずです (mod. スレッドプールスレッドを使用してシリアルポートの読み取りをブロックします)。

ビーズとワイヤーに油が十分に注がれていれば、そろばんで実行できる 2 つの 9600 ボー シリアル ポート。

于 2012-04-12T09:56:36.653 に答える
1

COMポートから読み書きしているため、これが発生すると思われます。その要因がなければ、これらはすべて同じように実行されるはずです。これは、(チェックした場合)すべてが通常の優先度のスレッドで実行されているためです。

I /O 完了ポートとスレッド プールを調べて、この奇妙な動作を説明できるかどうかを確認してください。

于 2012-04-12T07:00:37.873 に答える