我有一个通过串口与微控制器通信的应用程序。我想在后台工作器中定期检查控制器的状态,并允许用户通过发送命令和接收响应异步(通过用户界面)与控制器交互。
UI和后台工作程序使用SerialCommunication静态类:
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");
}
}
}
}
}
串行端口在应用程序启动时初始化。连续在UI或后台工作程序中调用SerialWrite
和SerialRead
。
我想避免命令从另一个线程中执行的另一个命令接收响应的情况。目前,我已经在发送命令之前在SerialWrite中等待接收命令(对于SerialRead完成),但是我担心这会阻止UI(最多waitForTransmissionTimeout
如果从那里执行SerialWrite,则为秒数。
那么同步SerialPort操作的最佳方法是什么?
答案 0 :(得分:1)
我不知道整个情况,但在我看来,你可以使用一个简单的锁定序列化你的写入,然后读取,如下所示:
static class SerialCommunication
{
static SerialPort serialPort;
static string endOfString = "" + char.MinValue;
static readonly object _commandLock = new object();
public static string SendCommand(string text) {
lock (_commandLock) {
SerialWrite(text);
return SerialRead();
}
}
private static string SerialRead() {
try {
return serialPort.ReadTo(endOfString);
}
catch (TimeoutException) {
throw new Exception(Properties.Resources.serial_read_timeout);
}
}
private static void SerialWrite(string text) {
try {
serialPort.Write(text);
}
catch (TimeoutException) {
throw new Exception(Properties.Resources.serial_write_timeout);
}
}
}