如何同步SerialPort操作?

时间:2016-05-28 18:04:05

标签: c# wpf multithreading serial-port synchronization

我有一个通过串口与微控制器通信的应用程序。我想在后台工作器中定期检查控制器的状态,并允许用户通过发送命令和接收响应异步(通过用户界面)与控制器交互。

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或后台工作程序中调用SerialWriteSerialRead

我想避免命令从另一个线程中执行的另一个命令接收响应的情况。目前,我已经在发送命令之前在SerialWrite中等待接收命令(对于SerialRead完成),但是我担心这会阻止UI(最多waitForTransmissionTimeout如果从那里执行SerialWrite,则为秒数。

那么同步SerialPort操作的最佳方法是什么?

1 个答案:

答案 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);
        }
    }
}