Closed AndreiGorlov closed 7 years ago
I've had a few Device Errors on our hardware too, usually on the first read if at all. Although I found they could be ignored. Have you tried catching it and repeating?
Catching and repeating doesn't work. ReadExisting() constantly throws exception after third call. First call returns empty string, second call returns null.
Sounds like the reading thread died. Can you please provide .net logs?
Debug output with enabled trace:
IO.Ports.SerialPortStream Error: 0 : COM6: SerialThread: DoWaitCommEvent: Result: 87
IO.Ports.SerialPortStream Error: 0 : COM6: SerialThread: Died from Value does not fall within the expected range.
The thread 0x2628 has exited with code 0 (0x0).
Exception thrown: 'System.IO.IOException' in RJCP.SerialPortStream.dll
The driver doesn't support the OS Call WaitCommEvent
, which is pretty fundamental to the SerialPortStream
implementation on Windows (it tells me when flush has occurred, when bytes are available, etc.)
As a fix can only be made with the hardware to test (I have no idea what this driver is doing), would you be willing to make some changes and debug? It will probably take some time before we get to a final solution.
The first would be to comment out the exception in the method DoWaitCommEvent
from CommOverlappedIo.cs
and see what happens:
private bool DoWaitCommEvent(out NativeMethods.SerialEventMask mask, ref NativeOverlapped overlap)
{
bool result = UnsafeNativeMethods.WaitCommEvent(m_ComPortHandle, out mask, ref overlap);
if (!result) {
int w32err = Marshal.GetLastWin32Error();
int hr = Marshal.GetHRForLastWin32Error();
if (w32err != WinError.ERROR_IO_PENDING) {
SerialTrace.TraceSer.TraceEvent(System.Diagnostics.TraceEventType.Error, 0,
"{0}: SerialThread: DoWaitCommEvent: Result: {1}", m_Name, w32err);
// Marshal.ThrowExceptionForHR(hr);
}
} else {
ProcessWaitCommEvent(mask);
}
return !result;
}
That will make the main thread think that the result is pending (it will never arrive) effectively disabling it. Getting the EOF, flushing and errors from the driver won't work as expected. But I'm hoping at least the OS call ClearCommError
will work. I'll need full logs for your test program to see what the effects are.
After commenting out Marshal.ThrowExceptionForHR(hr)
my program began to receive data from the device.
Trace:
IO.Ports.SerialPortStream Error: 0 : COM6: SerialThread: DoWaitCommEvent: Result: 87
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: DoReadEvent: ReadFile(628, 3007597484464, 1048576) == False
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: 7 bytes
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: End=0; Bytes=7
IO.Ports.SerialPortStream Verbose: 0 : COM6: CommEvent: EV_RXCHAR
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: DoReadEvent: ReadFile(628, 3007597484471, 1048569) == False
IO.Ports.SerialPortStream Verbose: 0 : COM6: HandleEvent: Chars; NoError; NoChange;
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: 0 bytes
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: DoReadEvent: ReadFile(628, 3007597484471, 1048569) == False
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: 7 bytes
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: End=7; Bytes=7
IO.Ports.SerialPortStream Verbose: 0 : COM6: CommEvent: EV_RXCHAR
IO.Ports.SerialPortStream Verbose: 0 : COM6: HandleEvent: Chars; NoError; NoChange;
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: DoReadEvent: ReadFile(628, 3007597484478, 1048562) == False
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: 0 bytes
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: DoReadEvent: ReadFile(628, 3007597484478, 1048562) == False
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: 7 bytes
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: End=14; Bytes=7
...
This is going to take a little time to get a full solution (I can only work on this in my free time). I would want to build in a detection mechanism for this. Then I need to deactivate or change some behaviour, such as flushing.
I need to analyse the logs. I might have some more tests that add extra logging. I want to check how the GetReceiveStat function works on your hardware.
Ready to help.
@splitice you indicated that you sometimes had the Device Error also but it only happened a few times. Do you have any logs for that situation? I've spent a few hours trying to reproduce and analysing code, but I can't see how this can occur. If you can, could you open a new issue?
I have the same hardware - Arduino Uno clone (with CH340 on board) and I face the same problem with DataReceived event (the Read thread exited with code 0). When commenting the line Marshal.ThrowExceptionForHR(hr)
the code worked
I've made a commit to the branch "feature/dotnet-98" if you could please test. It's slightly different. If it's OK, I'll merge and put in the next release.
feature/dotnet-98 works fine with CH340. Trace, just in case:
IO.Ports.SerialPortStream Error: 0 : COM6: SerialThread: DoWaitCommEvent: Result: 87
IO.Ports.SerialPortStream Warning: 0 : COM6: SerialThread: Not processing WaitCommEvent events
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: DoReadEvent: ReadFile(648, 2154877655472, 1048576) == False
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: 7 bytes
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: End=0; Bytes=7
IO.Ports.SerialPortStream Verbose: 0 : COM6: CommEvent: EV_RXCHAR
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: DoReadEvent: ReadFile(648, 2154877655479, 1048569) == False
IO.Ports.SerialPortStream Verbose: 0 : COM6: HandleEvent: Chars; NoError; NoChange;
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: 0 bytes
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: DoReadEvent: ReadFile(648, 2154877655479, 1048569) == False
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: 7 bytes
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: End=7; Bytes=7
IO.Ports.SerialPortStream Verbose: 0 : COM6: CommEvent: EV_RXCHAR
IO.Ports.SerialPortStream Verbose: 0 : COM6: HandleEvent: Chars; NoError; NoChange;
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: DoReadEvent: ReadFile(648, 2154877655486, 1048562) == False
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: 0 bytes
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: DoReadEvent: ReadFile(648, 2154877655486, 1048562) == False
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: 7 bytes
IO.Ports.SerialPortStream Verbose: 0 : COM6: SerialThread: ProcessReadEvent: End=14; Bytes=7
Merged on master
Trying to read output from Arduino Uno clone (with CH340 on board):
ReadExisting() throws:
Same code with System.IO.Ports.SerialPort works fine.
Windows 10 x64 1703, .NET 4.6.1