シリアルポート経由でマイクロコントローラと通信するアプリケーションがあります。バックグラウンドワーカーでコントローラーのステータスを定期的に確認し、ユーザーがコマンドを送信して応答を受け取ることで、ユーザーインターフェイスを介して非同期にコントローラーと対話できるようにします。SerialPortの操作を同期させる方法は?
UIやバックグラウンドワーカーは、シリアル通信静的クラスを使用します。
static class SerialCommunication
{
static SerialPort serialPort;
static int readWriteTimeout = 1000; // [ms]
static int waitForTransmissionTimeout = 2; // [s]
static string rxData = "", endOfString = "" + char.MinValue;
static bool WaitingForSerialData = false; // Set in SerialWrite(), cleared in SerialRead()
[...]
public static string SerialRead()
{
try
{
rxData = serialPort.ReadTo(endOfString);
}
catch (TimeoutException)
{
WaitingForSerialData = false;
throw new Exception(Properties.Resources.serial_read_timeout);
}
WaitingForSerialData = false;
return rxData;
}
public static void SerialWrite(string text)
{
DateTime start = DateTime.Now;
while (WaitingForSerialData) // Avoids the situation in which a command executed on a thread receives the response for the command executed from a different thread
{
if (!WaitingForSerialData)
{
try
{
WaitingForSerialData = true; // All commands wait for confirmation/data, so it is normal to set this boolean value for every serial transmission
serialPort.Write(text);
}
catch (TimeoutException)
{
throw new Exception(Properties.Resources.serial_write_timeout);
}
}
else
{
System.Threading.Thread.Sleep(100);
if ((DateTime.Now - start).Seconds >= waitForTransmissionTimeout)
{
throw new Exception("Timeout");
}
}
}
}
}
シリアルポートは、アプリケーションの起動時に初期化されます。 SerialWrite
およびSerialRead
は、UIまたはバックグラウンドワーカーで連続して呼び出されます。
コマンドが別のスレッドで実行された別のコマンドからの応答を受け取ることを避けたいです。現在、コマンドを送信する前に(SerialReadを終了するために)コマンドを受け取るためにSerialWriteで待機する実装を実装しましたが、SerialWriteが実行された場合にUIをブロックすることができます(最大waitForTransmissionTimeout
秒間)そこ。
SerialPortの操作を同期するにはどうすればよいですか?
だから、_all_コマンドはSerialWriteが続いています応答を受信するSerialReadによって?もしそうなら、なぜ単一のSendCommandなどで読み書き操作を組み合わせないのですか? – Evk
@Evkしかし、SendCommandがバックグラウンドワーカースレッドなどで実行され、UIの実行の直後(実行が終了する前)に何が起こるのでしょうか? –
シンプルなロックで全体の操作(write + following read)を保護する必要があります。次に、バックグラウンドワーカーが実行を終了する前にUIがコマンドを送信すると、完了するまで待機します。もちろん、UIスレッドからその操作を実行しないでください。バックグラウンドスレッドから実行し、完了したら結果をUIスレッドに返します(ユーザーに結果を表示する)。そのようなことをUIスレッドで直接実行しないでください。 – Evk