@TomWrあなたが正しいです、私がこれを読んでいるところからです。私のコメントで以下
あなたのスニペット:
try
{
// Let's check how many bytes are available on the Serial Port
btr = serialPort1.BytesToRead;
// Something? Alright then, let's wait 300 ms.
if (btr > 0)
Thread.Sleep(300);
// Let's check again that there are some bytes available the Serial Port
btr = serialPort1.BytesToRead;
// ... and if so wait (maybe again) for 300 ms
// Please note that, at that point can be all cumulated about 600ms
// (if we actually already waited previously)
if (btr > 0)
{
Thread.Sleep(300);
btr = serialPort1.BytesToRead;
numbytes = serialPort1.Read(stuffchar, 0, btr);
for (x = 0; x < (numbytes); x++)
{
// Seems like a useless overhead could directly use
// an Encoding and ReadExisting method() of the SerialPort.
cc = (stuffchar[x]);
stuff += Convert.ToString(Convert.ToChar((stuffchar[x])));
}
は私の推測では、すでにデータがデバイスによって送信されたとのことができます彼らに
をフェッチしているかどうかを確認するために、基本的には、おそらく、idstamによって上記されたように同じですこのコードを適切なSerialPortメソッドで簡単にリファクタリングすることは、実際にはシリアルポート上で利用可能なデータがあるかどうかをチェックするために、はるかに簡潔な方法があるからです。
「ポートに何バイトありますか?何かがあれば、300ミリ秒後に同じことをやり直してください。"これは悲惨なことに
で終了します"このように2回300 ms = 600ms、または1回だけ(最初にあったかどうかに応じて)、またはまったく何もしません(このUIを介して通信しているデバイスによってThread.SleepがUIをブロックして以来本当に不愉快なことがあります)。 "
まず、同じコードベースを維持しようとしていることを考えてみましょう。
ReadTimeoutプロパティを使用してタイムアウト例外をキャッチするのではなく、読みやすくするためにはそれ以上ではなく、Convert.ToChar()呼び出しを使用せずにStringを直接取得するのはなぜですか?
私は、コードがCやC++(あるいは少なくとも根本的な理由)から移植されたソフトウェアのバックグラウンドを持っている人から移植されていると感じます。
とにかく、利用可能なバイト数のチェックに戻ると、シリアルポートデータが別のスレッド/ BackgroundWorker/Taskハンドラでフラッシュされない限り、私は特にそれが2回チェックされる理由は見当たりませんコード化される。
もっと速くするには?実際には、シリアルポートに実際にデータがある場合は、追加の遅延が発生するためです。それは私にとってそれほど意味がありません。
スニペットを少し良くするもう1つの方法は、ReadExisting()を使用してポーリングすることです。
そうでない場合は、SerialPort BaseStreamを使用して非同期メソッドを検討することもできます。
あなたのコードベースの残りの部分、つまりコンテキストにアクセスすることなく、言い表すのはかなり難しいです。
目的/プロトコルの詳細については、何をすべきかについてのヒントを示します。さもなければ、私はちょうどこれが文脈の中でもう一度、コード化されていないと思われると言うことができます。
ハンスがUIの反応性について言及したことは、実際にはあなたのスニペットがUIではないスレッドで実行されていることを願っています(あなたのポストでUIがポーリングしているまだスニペットが別の労働者のためにあることを望む)。
UIスレッドの場合は、UIが実際にユーザーのやりとりに反応しないようにThread.Sleep呼び出しがあるたびにブロックされ、エンドユーザーに不満を感じることがあります。
DataReceivedイベントを購読し、ハンドラを使用して必要な/必要な処理を実行することもできます(バッファや値の比較など)。
monoはまだこのイベントのトリガーを実装していませんが、プレーンなMS .NETの実装に対して実行している場合は、マルチスレッドの手間がなくても問題ありません。要するに
:スレッド(S)、それはUIがある場合
- が、その後介して別のスレッドを使用するUIの応答性についてのあなたのスニペットのケアと心を取って(している)されて
- チェックスレッド、BackgroundWorker(スレッドプール)、またはタスク。UIスレッドの同期の
- の手間を避けるために
- ストリーム非同期メソッドは、目的が本当に二重の300ミリ秒のスレッドスリープメソッド呼び出し
- に値するかどうかをあなたが直接、代わりに文字列を取得することができます参照してください後者のチェックで、自分でバイトを収集するのではなく、操作を実行する場合(選択されたエンコーディングがあなたのニーズを満たすことができる場合)収集すること。
ストリーム非同期メソッド(例: 'port.BaseStream.ReadAsync')は別のスレッドを使用しません....それは良いことです。複数のスレッドからデータ構造へのアクセスを同期させることや、スレッド間のUIコントロールの使用を整理することを心配する必要はありません。イベントハンドラが 'await'を返すか呼び出すたびに、データ構造を一貫した状態にしておきます。 –
@BenVoigt http://referencesource.microsoft.com/#mscorlib/system/io/stream.cs,e224b4bec8748849 async/awaitはTaskを使用しているため、Threadpoolです。したがって、別のスレッドで実行できますが、必ずしもそうではありません。 私が間違っていると思われる場合は、もう少し説明してください。 特にUIが関連している場合は、同期に関して合意しました。 – Ehouarn
タスクオブジェクトは、デフォルトで現在のコンテキストで実行され、UIアプリケーションではデフォルトのコンテキストはUIメッセージディスパッチャーです。余分なスレッドは使用されません。これで作業をワーカースレッドに強制することができますが、それはI/O、特にシリアルI/Oに対しては愚かなことになります。ワーカースレッドは、CPUバインド操作にのみ有効です。 –