Проверка SerialPort.BytesToRead и использование TimeoutException в цикле чтения?

У меня есть класс .NET С#, который использует System.IO.Ports.SerialPort для связи через последовательный порт. Он включает в себя поток, который непрерывно читает последовательный порт в цикле.

Я всегда думал, что использование исключений как части нормального выполнения программы — это плохо, но, просматривая веб-страницы, я вижу много примеров использования блокировки чтения и TimeoutException для ожидания входящих данных, например:

while (true)
{
    try
    {
        serialPort.Read(buffer, offset, count);
        /* Processing code here */
    }
    catch (TimeoutException)
    { }
}

Не лучше ли проверить SerialPort.BytesToRead() перед выдачей Read, как в этом примере:

while (true)
{
    if (serialPort.BytesToRead() <= 0)
    {
        /* Wait for event signal or similar. */
    }

    serialPort.Read(buffer, offset, count);
    ProcessData();
}

person Oberon    schedule 18.02.2013    source источник
comment
Существуют неотъемлемые накладные расходы, связанные с исключением, заполнением свойств, созданием трассировки стека и т. д., поэтому использование исключений в обычном потоке программы, как правило, является плохой идеей.   -  person Dutts    schedule 18.02.2013
comment
Можно использовать исключения и подавлять их. Исключение тайм-аута, потому что у вас нет данных, в порядке. Первый подход с большим тайм-аутом, например, 2 секунды, заставляет ваш поток ждать почти без использования ЦП. Второй подход заставляет вас использовать спин-блокировку, которая использует 100% ЦП. За исключением того, что вы используете процесс флага только для Windows, используя событие DataReceived. Но это будет слишком усложнять, а также использовать гораздо больше ресурсов процессора. Посмотрите [ответ User3279361]: (stackoverflow.com/questions/10172996/)   -  person Gustavo Garcia    schedule 21.02.2017


Ответы (2)


Второй подход определенно лучше. Исключения не должны использоваться для управления нормальным ходом программы.

Кроме того, первый подход сильно загромождает процесс отладки, особенно если вы настроите IDE на прерывание работы при каждом сгенерированном исключении.

person Eren Ersönmez    schedule 18.02.2013
comment
Просто чтобы уточнить, вы имели в виду, что подход first действительно загромождает ваш опыт отладки, верно? - person Oberon; 18.02.2013
comment
Я не согласен. Иногда вы получите 'serialPort.BytesToRead()== 0', но еще не все получено. Поэтому тайм-аут считается максимальным временем ожидания ответа, после которого предполагается доставка всей полезной нагрузки. - person Natxo; 12.04.2017
comment
@Naxto вопрос касается использования BytesToRead как средства узнать, когда начать чтение, чтобы вы не пытались постоянно пытаться читать и получать исключения тайм-аута в ожидании прибытия сообщения. Цель состоит в том, чтобы не узнать, что все сообщение было получено. - person Eren Ersönmez; 12.04.2017

Не читайте порт, у вас есть специальная функция:

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
     int n = serialPort1.BytesToRead;
     ...
}
person user5459655    schedule 18.10.2015