.NET SerialPort DataReceived 事件未触发

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2281618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 13:55:49  来源:igfitidea点击:

.NET SerialPort DataReceived event not firing

.netserial-port

提问by Klay

I have a WPF test app for evaluating event-based serial port communication (vs. polling the serial port). The problem is that the DataReceived event doesn't seem to be firing at all.

我有一个 WPF 测试应用程序,用于评估基于事件的串行端口通信(与轮询串行端口)。问题是 DataReceived 事件似乎根本没有触发。

I have a very basic WPF form with a TextBox for user input, a TextBlock for output, and a button to write the input to the serial port.

我有一个非常基本的 WPF 表单,其中包含用于用户输入的 TextBox、用于输出的 TextBlock 和用于将输入写入串行端口的按钮。

Here's the code:

这是代码:

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);
    }
}

Now, here are the complicating factors:

现在,这里是复杂的因素:

  1. The laptop I'm working on has no serial ports, so I'm using a piece of software called Virtual Serial Port Emulator to setup a COM2. VSPE has worked admirably in the past, and it's not clear why it would only malfunction with .NET's SerialPort class, but I mention it just in case.

  2. When I hit the button on my form to send the data, my Hyperterminal window (connected on COM2) shows that the data is getting through. Yes, I disconnect Hyperterminal when I want to test my form's ability to read the port.

  3. I've tried opening the port before wiring up the event. No change.

  1. 我正在使用的笔记本电脑没有串口,所以我使用了一个名为 Virtual Serial Port Emulator 的软件来设置 COM2。VSPE 过去工作得非常好,目前尚不清楚为什么它只会在 .NET 的 SerialPort 类中出现故障,但我提到它以防万一。

  2. 当我点击表单上的按钮发送数据时,我的超级终端窗口(连接在 COM2 上)显示数据正在通过。是的,当我想测试我的表单读取端口的能力时,我断开了超级终端。

  3. 我已经尝试在连接事件之前打开端口。没变。

I've read through another post here where someone else is having a similar problem. None of that info has helped me in this case.

我已经在这里阅读了另一篇文章,其中其他人也遇到了类似的问题。在这种情况下,这些信息都没有帮助我。

EDIT:

编辑:

Here's the console version (modified from http://mark.michaelis.net/Blog/TheBasicsOfSystemIOPortsSerialPort.aspx):

这是控制台版本(从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);
    }
}

This should eliminate any concern that it's a Threading issue (I think). This doesn't work either. Again, Hyperterminal reports the data sent through the port, but the console app doesn't seem to fire the DataReceived event.

这应该消除任何关于它是线程问题的担忧(我认为)。这也行不通。同样,超级终端报告通过端口发送的数据,但控制台应用程序似乎没有触发 DataReceived 事件。

EDIT #2:

编辑#2:

I realized that I had two separate apps that should both send and receive from the serial port, so I decided to try running them simultaneously...

我意识到我有两个独立的应用程序应该从串行端口发送和接收,所以我决定尝试同时运行它们......

If I type into the console app, the WPF app DataReceived event fires, with the expected threading error (which I know how to deal with).

如果我输入控制台应用程序,WPF 应用程序 DataReceived 事件将触发,并带有预期的线程错误(我知道如何处理)。

If I type into the WPF app, the console app DataReceived event fires, and it echoes the data.

如果我输入 WPF 应用程序,控制台应用程序 DataReceived 事件会触发,并且它会回显数据。

I'm guessing the issue is somewhere in my use of the VSPE software, which is set up to treat one serial port as both input and output. And through some weirdness of the SerialPort class, one instance of a serial port can't be both the sender and receiver. Anyway, I think it's solved.

我猜问题出在我使用 VSPE 软件的某个地方,该软件设置为将一个串行端口同时作为输入和输出。通过 SerialPort 类的一些奇怪之处,串行端口的一个实例不能既是发送者又是接收者。反正我觉得已经解决了。

采纳答案by Klay

I can only surmise that the problem was indeed with the Virtual Serial Port Emulator program. this is NOT to say there is a problem with that software: VSPE has worked very well for me so far. But there was some conflict between my code and how I had set up the VSPE connector.

我只能推测问题确实出在 Virtual Serial Port Emulator 程序上。这并不是说该软件有问题:到目前为止,VSPE 对我来说效果很好。但是我的代码与我设置 VSPE 连接器的方式之间存在一些冲突。

回答by Andreiz

port.DtrEnable = true;

This solved it for me, the DataTransmitReady flag was not enabled, so no data was received.

这为我解决了问题,未启用 DataTransmitReady 标志,因此未收到任何数据。

回答by Dave Swersky

I can't say for sure, but there could be a threading issue. WPF handles threading differently, and the polling of the virtual port is asynchronous, I believe. Have you tried this with a Windows Forms or console application to prove that it can work at all?

我不能肯定地说,但可能存在线程问题。WPF 以不同的方式处理线程,我相信虚拟端口的轮询是异步的。您是否尝试过使用 Windows 窗体或控制台应用程序来证明它完全可以工作?

回答by Roast

I use the exact same setup, it works perfectly now but had to solve many many problems to get there.

我使用完全相同的设置,它现在可以完美运行,但必须解决许多问题才能到达那里。

Here is why my initial declaration looks like:

这就是为什么我的初始声明看起来像:

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);

I seperated the open port and close port methods since i often check if the com port has been closed.

我将打开端口和关闭端口方法分开,因为我经常检查 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
    }
}

Lastly, verify that your Virtual Com Port driver is installed properly and that you are using the right port, a plug and play for my adapter was not enough. If you want to create a sort of control that will allow you to pick the ports available at runtime, the following command will give you the available ports:

最后,验证您的 Virtual Com 端口驱动程序是否正确安装,并且您使用的是正确的端口,我的适配器的即插即用是不够的。如果您想创建一种允许您在运行时选择可用端口的控件,以下命令将为您提供可用端口:

System.IO.Ports.SerialPort.GetPortNames()

回答by paIncrease

I have had similar issue when running such a driver from a Form, as well, though no VSPE just a plain SP. Believe this was a STA-model issue as moving to including it in a console app fixed enough.

从 Form 运行这样的驱动程序时,我也遇到了类似的问题,尽管没有 VSPE 只是一个普通的 SP。相信这是一个 STA 模型问题,因为将其包含在足够固定的控制台应用程序中。

回答by Gina

I use VSPE too! It does work wonderfully.. I was having this same problem and the way I fixed it was to make the two com ports a PAIR in VSPE instead of just creating two virtual com ports

我也用 VSPE!它确实工作得很好..我遇到了同样的问题,我修复它的方法是在 VSPE 中使两个 com 端口成对,而不是仅仅创建两个虚拟 com 端口

回答by Richard J Foster

I ran into a similarly odd problem recently, but only on some machines. As Dave Swerskynoted, this may have been a threading issue, especially if you were running under .NET 4.0 or later.

我最近遇到了一个类似的奇怪问题,但仅限于某些机器。正如Dave Swersky 所指出的,这可能是一个线程问题,尤其是当您在 .NET 4.0 或更高版本下运行时。

In .NET 4.0 the event handler is triggered on a ThreadPool thread, and under certain circumstances there may be a substantial delay before that occurs. (In my code, which had been working perfectly under .NET 2.0, problems were observed as soon as we upgraded to .NET 4.5. The event handler would often be triggered much later than would be expected, and sometimes it would not get triggered at all!)

在 .NET 4.0 中,事件处理程序是在 ThreadPool 线程上触发的,在某些情况下,在此之前可能会有相当长的延迟。(在我的代码中,它在 .NET 2.0 下运行良好,当我们升级到 .NET 4.5 时就发现了问题。事件处理程序通常会比预期更晚触发,有时它不会在全部!)

Calling ThreadPool.SetMinThreads(...)with a bigger value for the completion threads made the issue disappear as quickly as it had arrived. In the context of our application ThreadPool.SetMinThreads(2, 4)was sufficient. On the machines where the problem was observed, the default values (as obtained by calling ThreadPool.SetMinThreads) were both 2.

ThreadPool.SetMinThreads(...)为完成线程调用更大的值会使问题尽快消失。在我们的应用程序的上下文中ThreadPool.SetMinThreads(2, 4)就足够了。在观察到问题的机器上,默认值(通过调用 获得ThreadPool.SetMinThreads)都是 2。

回答by JD - DC TECH

Two days ago I had the same problem and it was a big headache because I needed to deliver the app today. So.. after too much googleashion I supposed that the issue was another thing and not my code.

两天前我遇到了同样的问题,这让我很头疼,因为我今天需要交付应用程序。所以......经过太多的googleashion,我认为问题是另一回事,而不是我的代码。

My solution was uninstall McAfeeantivirus and all things related with this. When I saw the logs of McAfee it had records about stop threads and I assumed that the SerialDataReceivedEventHandler()run in a thread.

我的解决方案是卸载 McAfee防病毒软件以及与此相关的所有内容。当我看到 McAfee 的日志时,它有关于停止线程的记录,我认为是SerialDataReceivedEventHandler()在一个线程中运行。

I hope this solution works for you. Regards.

我希望这个解决方案对你有用。问候。

回答by Luo Qiongyu

I am using the Virtual Serial Port Driver. This problem takes me the whole day. And finally fix by creating a pair of port. One port send message and another one receive message instead of using the same port to send and receive message. I guess that is how Null Modem Emulator works.

我正在使用虚拟串行端口驱动程序。这个问题困扰了我一整天。最后通过创建一对端口来修复。一个端口发送消息,另一个端口接收消息,而不是使用相同的端口来发送和接收消息。我想这就是 Null Modem Emulator 的工作原理。

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

Result: Data Received: Hello World Press any key to continue...

结果:收到的数据:Hello World 按任意键继续...