Завершить вызов SerialPort.ReadLine () - PullRequest
2 голосов
/ 08 февраля 2011

Я пишу программу, которая анализирует ответы на AT-команды от GSM-модема, подключенного к ПК через последовательный порт. В этой программе у меня есть поток, который «слушает» все ответы на последовательном порту. Затем он может либо отправить ответ в очередь для потока, который запросил выполнение команды (которая блокируется, когда элемент помещен в эту очередь), либо он может сгенерировать событие, сигнализирующее о получении незапрошенного кода результата.

В настоящее время поток (метод) основан на методе SerialPort.ReadLine и является частью написанного мною класса "GsmModem". Когда вызывается метод GsmModem.Close (). Мне нужно дать сигнал потоку прослушивателя завершить работу и дождаться его завершения, затем закрыть мой последовательный порт. Мой текущий код не очень элегантен, поскольку он основан на исключении тайм-аута последовательного порта. Поток вращается с serialPort.ReadLine (), выбрасывающим исключения Timeout и проверяющим флаг 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, рекомендуется ли это? Наконец, если вы можете предложить что-то лучшее, это было бы здорово.

Заранее благодарю за любые комментарии или помощь людям.

1 Ответ

1 голос
/ 10 февраля 2011

Я рекомендую использовать событие SerialPort.DataReceived. Это будет означать сохранение собственного буфера для последовательных данных, но это не очень сложно. Сделайте это, и вам не придется поддерживать поток слушателя. Вместо этого, когда вы будете готовы закрыть последовательный порт, просто удалите делегат DataReceived и закройте порт.

Также неплохо бы обработать событие SerialPort.ErrorReceived. Возможно, вы уже делаете это.

...