Многопортовый асинхронный ввод-вывод через последовательный порт в C # - PullRequest
2 голосов
/ 23 марта 2009

Я пытаюсь написать тестовое приложение для последовательного ввода-вывода ( RS-232 ) с несколькими модулями в C #, и у меня возникает проблема с моим отсутствием опыта работы с потоками, поэтому я прошу отзывы о наиболее известном методе.

У меня есть пул COM-портов COM1-16, каждый из которых может читать / писать в любое время, и мне нужно иметь возможность управлять ими одновременно. Это ситуация для пула потоков? Какое руководство по структурированию этого апплета?

Edit: После проверки мне стало интересно, действительно ли мне здесь нужно создавать асинхронные потоки, я мог бы просто поддерживать состояния для каждого COM-порта и выполнять логику потока (т. Е. Statemachine) для каждого COM-порта отдельно.

Ответы [ 4 ]

2 голосов
/ 23 марта 2009

Большая часть трудностей, связанных с последовательным портом, сосредоточена вокруг предположения. Предполагается, что последовательный порт получает данные в виде удобных кусков и того, что ожидается.

Вот пример. Я знаю, что мой приемник GPS отправляет линии (заканчивается CRLF). Это пример одного из предложений NMEA:

$ GPGSV, 3,1,11,10,75,053,29,29,52,311,32,24,50,298,30,02,39,073,30 * 77

Однако обработчик событий последовательных портов DataReceived может (обычно это происходит на моем ПК) запускаться несколько раз с кусками этих данных.

событие пожара - данные

1 $
2 GPGSV,3,1,11,10
3 ,75,053,29,29,52,311,32,24,50,298,30,02,39,073,30*77

Вместо того чтобы бороться с этим, я создал несколько подпрограмм, которые получают данные всякий раз, когда происходит событие, и ставят его в очередь. Когда мне нужны данные, я вызываю некоторые другие подпрограммы, которые собирают данные обратно в куски размером Я хочу . Таким образом, используя мой пример первый и второй раз, когда я вызываю строку чтения (моя строка чтения), я получаю пустой ответ. В третий раз я получаю обратно все предложение NMEA.

Плохая новость в том, что я не C #. Код здесь SerialPort

В зависимости от скорости портов делегаты могут быть не лучшим выбором. Я проверил свои подпрограммы на скорости около 1 Мбит / с с использованием делегатов, а не с использованием делегатов. На тех скоростях не использовать делегатов было лучшим выбором.

Вот несколько советов от тех, кто в курсе

Ким Гамильтон

1 голос
/ 24 марта 2010

Если вы используете фонового работника, вы не будете брать маленький части данных, вы получите всю строку. Тебе нужно что-то вроде:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        serialPort1.Open();
        if (serialPort1.IsOpen)
        {
            while (keepReading)
            {
                backgroundWorker1.ReportProgress(0, serialPort1.ReadLine());
                //backgroundWorker1.ReportProgress(0, sentence.Split(','));
                // split_gps_data();
            }
        }
    }
}
0 голосов
/ 24 марта 2010

Вам необходимо знать, с какой скоростью приемник выдает данные. Раз в секунду, дважды в секунду, 5 раз ...

У меня была такая же проблема с чтением данных GPS. Вам нужно использовать фонового работника в C # для обновления ваших переменных, экран.

0 голосов
/ 23 марта 2009

.NET способ справиться с этим заключается в использовании событий и делегатов. Это приведет к созданию нескольких потоков, но это будет происходить таким образом, что вы не будете создавать их явно. Если вы создаете обработчик событий и добавляете его в событие DataReceived каждого порта, то когда любой порт получает данные, обработчик событий будет вызываться в отдельном потоке. Естественно, это означает, что метод должен быть реентерабельным, и что доступ к любым разделяемым структурам данных должен быть защищен от одновременного доступа.

Ваша подпрограмма обработчика будет делать что-то вроде следующего:

  1. Вызовите ReadExisting, чтобы получить доступные данные.
  2. Обработка данных.
  3. Готово.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...