Как создать надежный интерфейс последовательного порта в Windows Forms - PullRequest
0 голосов
/ 06 января 2019

Я запускаю новое приложение 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;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...