开发者

Finish a call to SerialPort.ReadLine()

开发者 https://www.devze.com 2023-02-09 07:15 出处:网络
I\'m writting a program that parses the replies to AT commands from a GSM modem connected to the PC via a serial port. In this program I\'ve got a thread that \"listens\" for all the replies on the se

I'm writting a program that parses the replies to AT commands from a GSM modem connected to the PC via a serial port. In this program I've got a thread that "listens" for all the replies on the serial port. Then it may either send the response to a queue for a thread that solicited the execution of a command (which is blocked while an item is posted to this queue) OR it can generate an event to signal the reception of an Unsolicited Result Code.

Currently the thread (method) is based on the SerialPort.ReadLine method, and is part of a class开发者_Python百科 I've written called "GsmModem". When the GsmModem.Close() method is called. I need to signal the "listener" thread to finish and wait for it to terminate then, close my serial port. My current code is not very elegant since it relies on the timeout exception of the serial port. The thread spins with the serialPort.ReadLine() throwing Timeout exceptions and checking the ManualResetEvent flag. I would really like to avoid this.

I've looked everywhere if it's possible to abort the call to SerialPort.Readline(), but the only solution seems the timeout exception.

Other possible way would be to use the SerialPort.DataReceived event to process the data and either enqueue it when received a new line or raise a new event when an unsolicited response is received (i dont know if this is a good idea).

The actual code looks like this:

private void ModemListenerThread()
{
    if (this._serialPort.IsOpen)
    {
        //Execute the thread wile we don't receive the "endThreadSignal"
        while(!this._endThreadEvent.WaitOne(0))
        {
            // Catch TimeoutException and spin checking for the ManualResetEvent
            try
            {
                // Read line
                string line = this._serialPort.ReadLine();
                if (String.IsNullOrWhiteSpace(line))
                    continue;
                //Check if no command was sent (not definitive code)
                if (_modemIsIdle)
                    this.OnUnsolicitedResponse(new EventArgs());
                else
                {
                    //Enqueue as reply to command()
                    lock ((this._itemQueue as ICollection).SyncRoot)
                    {
                        _itemQueue.Enqueue(line);
                        this._itemPostedEvent.Set();
                    }
                }
            }
            //Timeout is necessary to avoid the thread to block indefinitely
            catch (TimeoutException ex)
            {
                continue;
            }
        }
    }
}

Any suggestion on how to implement the processing of the replies would be appreciated. My main question here is: Is it possible to abort the call to readline? If not, can I implement the logic on the SerialPort.DataReceved event, is that recomended? Finally if you can suggest anything better it would be great.

Thank you in advance for any comments or help folks.


I recommend using the SerialPort.DataReceived event. It will mean maintaining your own buffer for the serial data, but that isn't very complicated. Do this and you won't have to maintain your listener thread. Instead, when you're ready to close the serial port, just remove the DataReceived delegate and close the port.

It is a good idea to handle the SerialPort.ErrorReceived event as well. You may already be doing this.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号