6
votes

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.

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.

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.

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

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.

EDIT #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).

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

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.

9

9 Answers

19
votes
port.DtrEnable = true;

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

3
votes

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?

3
votes

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.

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:

System.IO.Ports.SerialPort.GetPortNames()
0
votes

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.

0
votes

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

0
votes

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

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

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.

0
votes

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.

My solution was uninstall McAfee antivirus 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.

I hope this solution works for you. Regards.

0
votes

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.

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...

-1
votes

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.