完成对 SerialPort.ReadLine() 的调用

发布于 2024-10-16 11:34:37 字数 1958 浏览 6 评论 0原文

我正在编写一个程序,用于解析通过串行端口连接到 PC 的 GSM 调制解调器对 AT 命令的回复。在这个程序中,我有一个线程“监听”串行端口上的所有回复。然后,它可以将响应发送到请求执行命令的线程的队列(当将项目发布到该队列时该线程被阻塞),或者它可以生成一个事件来指示接收到未经请求的结果代码。

目前该线程(方法)基于 SerialPort.ReadLine 方法,并且是我编写的名为“GsmModem”的类的一部分。当调用 GsmModem.Close() 方法时。我需要向“侦听器”线程发出信号以完成并等待它终止,然后关闭我的串行端口。我当前的代码不是很优雅,因为它依赖于串口的超时异常。线程旋转,serialPort.ReadLine() 抛出超时异常并检查 ManualResetEvent 标志。我真的很想避免这种情况。

我到处寻找是否可以中止对 SerialPort.Readline() 的调用,但唯一的解决方案似乎是超时异常。

其他可能的方法是使用 SerialPort.DataReceived 事件来处理数据,并在收到新行时将其排入队列,或者在收到未经请求的响应时引发新事件(我不知道这是否是一个好主意)。

实际代码如下所示:

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;
            }
        }
    }
}

任何有关如何实现回复处理的建议将不胜感激。我的主要问题是:是否可以中止对 readline 的调用?如果没有,我可以实现 SerialPort.DataReceved 事件上的逻辑吗?是否推荐?最后,如果您能提出更好的建议,那就太好了。

预先感谢您的任何评论或帮助。

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 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陌路终见情 2024-10-23 11:34:37

我建议使用 SerialPort.DataReceived 事件。这意味着要维护自己的串行数据缓冲区,但这并不是很复杂。这样做,您就不必维护您的侦听器线程。相反,当您准备关闭串行端口时,只需删除 DataReceived 委托并关闭端口即可。

最好也处理 SerialPort.ErrorReceived 事件。您可能已经在这样做了。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文