I am using Win32 API (Overlapped IO) for serial port communication. I have used PInvoke to call the Win32 API from my C# code.
In my previous implementation, the receiver thread reads data by using Polling mechanism (Infinite while loop reads RX buffer periodically). Now, I am trying to use Event-Driven approach to read the data (Using WaitCommEvent API Call). We expect the new implementation will reduce the CPU usage and Speed-Up the communication.
But, After changing to Event-Driven approach, the communication is actually slowed down, taking twice the time to read when compared to Polling mechanism.
Can anyone suggest which one of these is the best approach improve the communication speed and reduce the CPU usage?
Below is my code snippet:
private void ReadDataForWindows()
{
var data = new byte[255];
// Specify a set of events to be monitored for the port.
if (SetCommMask(this.Handle, EV_DEFAULT))
{
while (this.Handle != (IntPtr)INVALID_HANDLE_VALUE)
{
uint eventMask = 0;
// Wait for an event to occur for the port.
eventMask = this.WaitForEvent();
if (eventMask == EV_RXCHAR)
{
this.ReadFromRXBuffer(data);
}
else if (eventMask == EV_ERR)
{
uint errors;
ClearCommError(this.Handle, out errors, IntPtr.Zero);
}
// Re-specify the set of events to be monitored for the port.
if (!SetCommMask(this.Handle, EV_DEFAULT))
{
break;
}
}
}
}
private void ReadFromRXBuffer(byte[] data)
{
uint dwBytesTransferred;
// Loop for waiting for the data.
do
{
// Read the data from the serial port.
this.Read(data, 255, out dwBytesTransferred);
// Display the data read.
if (dwBytesTransferred > 0)
{
if (this.DataReceived != null)
{
var dataReceived = new byte[dwBytesTransferred];
for (var i = 0; i < dwBytesTransferred; i++)
{
dataReceived[i] = data[i];
}
this.DataReceived(this, new ByteDataReceivedEventArgs(dataReceived, Convert.ToInt32(dwBytesTransferred)));
}
}
} while (dwBytesTransferred > 0);
}
private uint WaitForEvent()
{
uint eventMask = 0;
IntPtr evPtr = Marshal.AllocHGlobal(Marshal.SizeOf(eventMask));
Marshal.WriteInt32(evPtr, 0);
if (WaitCommEvent(this.Handle, evPtr, this.RxOvr.MemPtr) == false)
{
int error = Marshal.GetLastWin32Error();
// Operation is executing in the background
if (error == ERROR_IO_PENDING)
{
this.ReceiveSignal.WaitOne();
}
else
{
this.Fault = "WaitCommEvent() Failed. System Returned Error Code: " +
error.ToString();
return 0;
}
}
eventMask = (uint)Marshal.ReadInt32(evPtr);
return eventMask;
}