Я запускаю новое приложение Windows Form, которое должно читать сообщения данных ASCII, оканчивающиеся символом LF с удаленного устройства через последовательный порт. К сожалению, нет гарантии, что завершенное LF-сообщение будет завершено в одном непрерывном блоке. Хуже того, несколько сообщений могут быть отправлены в одном непрерывном блоке с символами LF где-то посередине. У меня нет большого опыта в программировании на Windows, и я надеюсь получить совет относительно подхода, который, на мой взгляд, имеет смысл.
Вот мои собственные рекомендации по проектированию: 1) делайте как можно меньше в обработчике событий DataReceived 2) обработка сообщения занимает много времени, поэтому делайте это так, чтобы не замедлять работу пользовательского интерфейса 3) я пытаясь создать приложение, которое послужит основой для будущих приложений, поэтому я не возражаю против разработки этой первой попытки.
Вот мой подход. У меня есть класс последовательного порта с обработчиком событий DataReceived. Когда данные обнаруживаются и вызывается обработчик события DataReceived, он просто получает символы, доступные в порту, помещает их в очередь (по одному символу за раз). Если в полученных данных есть перевод строки, обработчик события вызывает метод backgroundworker_DoWork. Этот метод удаляет данные из очереди, перестраивает сообщение или сообщения, завершенные LF, и обрабатывает данные, как в коде ниже.
Для этого не требуется много строк кода, но под капотом происходит много всего, поэтому я надеюсь получить некоторый ввод или даже указатель на хорошо структурированную реализацию последовательного порта C #.
Queue<char> portQ = new Queue<char>();
private BackgroundWorker backgroundWorker = new BackgroundWorker();
void btSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int bytesToRead = btSerialPort.BytesToRead;
char[] inBuffer = new char[bytesToRead];
btSerialPort.Read(inBuffer, 0, bytesToRead);
for(int i = 0; i < bytesToRead; i++)
portQ.Enqueue(inBuffer[i]);
if (inBuffer.Contains('\n'))
backgroundWorker.RunWorkerAsync(); //The DoWork event handler is defined in the serial port constructor
}
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
//Dequeue the characters and process the message(s) here;
}