Событие .NET SerialPort DataReceived не запускается

У меня есть тестовое приложение WPF для оценки связи последовательного порта на основе событий (вместо опроса последовательного порта). Проблема в том, что событие DataReceived вообще не запускается.

У меня есть очень простая форма WPF с TextBox для пользовательского ввода, TextBlock для вывода и кнопкой для записи ввода в последовательный порт.

Вот код:

public partial class Window1 : Window
{
    SerialPort port;

    public Window1()
    {
        InitializeComponent();

        port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
        port.DataReceived +=
            new SerialDataReceivedEventHandler(port_DataReceived);  
        port.Open();
    }

    void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        Debug.Print("receiving!");
        string data = port.ReadExisting();
        Debug.Print(data);
        outputText.Text = data;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Debug.Print("sending: " + inputText.Text);
        port.WriteLine(inputText.Text);
    }
}

Итак, вот усложняющие факторы:

  1. Ноутбук, над которым я работаю, не имеет последовательных портов, поэтому я использую программу под названием Virtual Serial Port Emulator для настройки COM2. VSPE отлично работал в прошлом, и непонятно, почему он будет работать неправильно только с классом SerialPort .NET, но я упомянул об этом на всякий случай.

  2. Когда я нажимаю кнопку в своей форме для отправки данных, мое окно Hyperterminal (подключенное к COM2) показывает, что данные проходят. Да, я отключаю Hyperterminal, когда хочу проверить способность моей формы читать порт.

  3. Я пробовал открыть порт перед подключением к мероприятию. Без изменений.

Я прочитал здесь еще один пост, где у кого-то похожая проблема. Ни одна из этих сведений мне в данном случае не помогла.

РЕДАКТИРОВАТЬ:

Вот версия консоли (измененная с http://mark.michaelis.net/Blog/TheBasicsOfSystemIOPortsSerialPort.aspx):

class Program
{
    static SerialPort port;

    static void Main(string[] args)
    {
        port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
        port.DataReceived +=
            new SerialDataReceivedEventHandler(port_DataReceived);
        port.Open();

        string text;
        do
        {
            text = Console.ReadLine();
            port.Write(text + "\r\n");
        }
        while (text.ToLower() != "q");
    }

    public static void port_DataReceived(object sender,
        SerialDataReceivedEventArgs args)
    {
        string text = port.ReadExisting();
        Console.WriteLine("received: " + text);
    }
}

Это должно устранить любые опасения, что это проблема с потоками (я думаю). Это тоже не работает. Опять же, Hyperterminal сообщает данные, отправленные через порт, но консольное приложение, похоже, не запускает событие DataReceived.

ИЗМЕНИТЬ №2:

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

Если я ввожу в консольное приложение, срабатывает событие DataReceived приложения WPF с ожидаемой ошибкой потоковой передачи (с которой я знаю, как бороться).

Если я ввожу в приложение WPF, срабатывает событие DataReceived консольного приложения, которое отображает данные.

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


person Klay    schedule 17.02.2010    source источник


Ответы (9)


port.DtrEnable = true;

Это решило проблему для меня, флаг DataTransmitReady не был включен, поэтому данные не были получены.

person Andreiz    schedule 07.10.2013
comment
Это сработало и у меня после 5 кропотливых часов возни с балансом, подключенным к планшету. Баланс одной компании (OHaus) нормально передавался без этой строки, баланс следующей компании (Sartorius) - нет. - person jaredbaszler; 30.06.2015
comment
Оказывается, для работы USB-драйвера Adafruit SAMD51 Arduino требуется набор DtrEnable. Спасибо за отзыв (шесть лет спустя)! - person Brad Oestreicher; 11.10.2019

Я не могу сказать точно, но может быть проблема с потоками. WPF по-разному обрабатывает потоки, и я считаю, что опрос виртуального порта асинхронный. Вы пробовали это с помощью Windows Forms или консольного приложения, чтобы доказать, что это вообще может работать?

person Dave Swersky    schedule 17.02.2010
comment
См. Версию для консоли выше. Не повезло. - person Klay; 17.02.2010

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

Вот почему мое первоначальное объявление выглядит так:

comControl = new SerialPort();

//This is important - determine your min nb of bytes at which you will fire your event, mine is 9
comControl.ReceivedBytesThreshold = 9; 

//register the event handlers
comControl.DataReceived += new SerialDataReceivedEventHandler(OnReceive);
comControl.PinChanged += new SerialPinChangedEventHandler(OnPinChanged);

Я разделил методы открытия и закрытия порта, так как часто проверяю, закрыт ли com-порт.

public bool OpenPort()
{
    try
    {
        //must keep it open to maintain connection (CTS)
        if (!comControl.IsOpen)
        {
             comControl.Open();
             comControl.RtsEnable = true;
        }
    }
    catch (Exception e)
    {
        //error handling here
    }
}

Наконец, убедитесь, что ваш драйвер Virtual Com Port установлен правильно и что вы используете правильный порт, для моего адаптера было недостаточно подключи и работай. Если вы хотите создать своего рода элемент управления, который позволит вам выбирать порты, доступные во время выполнения, следующая команда предоставит вам доступные порты:

System.IO.Ports.SerialPort.GetPortNames()
person Roast    schedule 17.02.2010
comment
После вашего редактирования я вижу, что вы исправили некоторые изломы, но вы упомянули, что из-за некоторой странности класса SerialPort один экземпляр последовательного порта не может быть одновременно отправителем и получателем. Это неверно. Класс SerialPort может быть как отправителем, так и получателем. Поскольку вы утверждаете, что все как-то работает, я не буду вдаваться в подробности :) - person Roast; 17.02.2010
comment
Что ж, тогда это определенно звучит так, будто странность не в классе SerialPort, а в его связи с программным обеспечением виртуального последовательного порта. - person Klay; 19.02.2010
comment
+1 - Я забыл установить для пина RTS значение Enabled. Я забыл про аппаратное управление потоком. - person J. Polfer; 09.05.2010

У меня была аналогичная проблема при запуске такого драйвера из формы, хотя VSPE не был просто SP. Поверьте, это была проблема с STA-моделью, поскольку переход к ее включению в консольное приложение был исправлен.

person paIncrease    schedule 01.03.2013

Я тоже использую VSPE! Это работает замечательно ... У меня была та же проблема, и я решил ее исправить, сделав два COM-порта ПАРой в VSPE вместо того, чтобы просто создать два виртуальных COM-порта.

person Gina    schedule 27.04.2013

Недавно я столкнулся с такой же странной проблемой, но только на некоторых машинах. Как отметил Дэйв Сверски, возможно, это была проблема с потоками, особенно если вы работали под .NET 4.0 или более поздней версии. .

В .NET 4.0 обработчик событий запускается в потоке ThreadPool, и при определенных обстоятельствах может произойти существенная задержка до того, как это произойдет. (В моем коде, который отлично работал под .NET 2.0, проблемы наблюдались, как только мы обновились до .NET 4.5. Обработчик событий часто запускался намного позже, чем ожидалось, и иногда он не запускался при все!)

Вызов ThreadPool.SetMinThreads(...) с большим значением для Благодаря потокам завершения проблема исчезла так же быстро, как и возникла. В контексте нашего приложения ThreadPool.SetMinThreads(2, 4) было достаточно. На машинах, на которых наблюдалась проблема, значения по умолчанию (полученные путем вызова _ 3_) оба были 2.

person Richard J Foster    schedule 24.07.2013

Два дня назад у меня была такая же проблема, и это была большая головная боль, потому что мне нужно было доставить приложение сегодня. Итак ... после слишком большого количества googlemod я решил, что проблема была в другом, а не в моем коде.

Мое решение было удалить антивирус McAfee и все, что с этим связано. Когда я увидел журналы McAfee, в нем были записи об остановленных потоках, и я предположил, что SerialDataReceivedEventHandler() выполняется в потоке.

Надеюсь, это решение сработает для вас. С Уважением.

person JD - DC TECH    schedule 03.12.2015

Я использую драйвер виртуального последовательного порта. Эта проблема занимает у меня целый день. И напоследок исправим, создав пару порт. Один порт отправляет сообщение, а другой - получает сообщение вместо того, чтобы использовать один и тот же порт для отправки и получения сообщения. Я предполагаю, что именно так работает эмулятор нуль-модема.

Dim mySerialPort As SerialPort = New SerialPort("COM1")
Dim mySerialPort2 As SerialPort = New SerialPort("COM2")

Sub Main()
    SerialPortCommunicate()
End Sub

Public Sub SerialPortCommunicate()
    mySerialPort.BaudRate = 9600
    mySerialPort.Parity = Parity.None
    mySerialPort.StopBits = StopBits.One
    mySerialPort.DataBits = 8
    mySerialPort.Handshake = Handshake.None
    mySerialPort.DtrEnable = True
    mySerialPort.RtsEnable = True

    mySerialPort2.BaudRate = 9600
    mySerialPort2.Parity = Parity.None
    mySerialPort2.StopBits = StopBits.One
    mySerialPort2.DataBits = 8
    mySerialPort2.Handshake = Handshake.None
    mySerialPort2.DtrEnable = True
    mySerialPort2.RtsEnable = True

    AddHandler mySerialPort2.DataReceived, AddressOf DataReceivedHandler

    mySerialPort.Open()
    mySerialPort2.Open()

    mySerialPort.Write("Hello World")

    Console.WriteLine("Press any key to continue...")
    Console.WriteLine()
    Console.ReadKey()
    mySerialPort.Close()
    mySerialPort2.Close()
End Sub

Private Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedEventArgs)
    Dim sp As SerialPort = CType(sender, SerialPort)
    Dim indata As String = sp.ReadExisting()
    Console.WriteLine("Data Received:")
    Console.Write(indata)
End Sub

Результат: Полученные данные: Hello World Нажмите любую клавишу, чтобы продолжить ...

person Luo Qiongyu    schedule 08.10.2019
comment
Не могли бы вы дать более конкретный ответ? Как вставить кусок кода или скриншоты конфигурации? - person Olympiloutre; 08.10.2019

Я могу только предполагать, что проблема действительно была в программе Virtual Serial Port Emulator. это НЕ означает, что с этим программным обеспечением есть проблемы: до сих пор VSPE у меня работал очень хорошо. Но был некоторый конфликт между моим кодом и тем, как я настроил коннектор VSPE.

person Klay    schedule 11.03.2010