これに対する答えを探すのに時間を費やしたところ、他のスレッドで役立つ情報がたくさん見つかりました。うまくいくようにコードを書いたと思いますが、結果には満足していません。
C# 経由で通信するハードウェアを設計しました。ハードウェアは USB 経由で接続し、OS で列挙した後、初期化ルーチンを実行します。その時点で、C# プログラムがコマンドの送信を開始するのを待つだけです。私の C# コードでは、ユーザーは「接続」ボタンを押す必要があります。これにより、コマンドと必要なペイロードが送信され、実行を継続する必要があることがハードウェアに通知されます。その後、ハードウェアはコマンドを ACK として送り返します。問題は、C# プログラムが ACK の受信を待たなければならないことですが、自由にブロックできる別のスレッドに分割する方法がわからないため、ハードウェアが応答するまで GUI が完全にフリーズします。ハードウェアがすぐに応答する場合は正常に動作しますが、接続できない場合、プログラムは無期限にフリーズしたままになります。
そうは言っても、いくつかのことが起こる必要があることは知っていますが、それらを実装する方法はわかりません。何よりもまず、ループに座ってブール値を待機することは正しい方法ではないと思いますが、AutoResetEvent を使用することは実際にはあまり良くないようです。タイマー、より多くのスレッド、または同様のものを含むより良い方法が必要です。
次のように、serialPort オブジェクトで DataReceived イベントを使用しています。
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
byte cmd = (byte)serialPort1.ReadByte();
if (cmd == (byte)Commands.USB_UART_CMD_MCU_CONNECT)
MCU_Connect_Received.Set();
}
buttonClick 関数 (「メイン」スレッド) では、プログラムは ACK を待っている間に停止します。
//Send the command to signal a connection
Send_Connection_Packet((byte)Commands.USB_UART_CMD_PC_CONNECT);
textBox1.AppendText("-I- Attempting to contact hardware...");
MCU_Connect_Received.WaitOne();
textBox1.AppendText("Success!" + Environment.NewLine);
理想的には、タイムアウトが切れたかどうかを知りたいので、「失敗しました!」と出力できます。「成功!」の代わりに。タイムアウトがないということは、上で述べたように、プロセスを強制終了するまで、永遠にそこに留まることも意味します。ハードウェアが見つからない可能性がありますが、見つかった場合は 1 秒未満で応答するはずなので、2 秒のタイムアウトで十分です。Thread.Sleep を使用してみましたが、GUI もフリーズしました。