Hi,
We are using a C++ dll from our C# code.
The C++ code reads data from a serial communication port, and fills up a buffer with the data read.
We are sometimes experiencing a big delay (around 5 seconds) when the C++ function returns.
The C# code looks something like this:
class Program
{
[DllImport("SerialCommunication.dll", EntryPoint = "SerialCommRead", SetLastError = true)]
protected static extern unsafe SERIAL_COM_STATUS SerialCommRead(uint handle,
[MarshalAs(UnmanagedType.LPArray)] byte[] buffer,
uint length, [MarshalAs(UnmanagedType.LPArray)] uint[] bytesRead);
protected void Read()
{
StreamWriter logWriter = new new StreamWriter("test.log", true);
SERIAL_COM_STATUS status = SerialCommRead(m_PortHandle, m_ReadBuffer,(uint)m_ReadBuffer.Length, bytesRead);
DateTime t = DateTime.Now;
logWriter.Write(t.Day.ToString() + "/" + t.Month.ToString() + "/" + t.Year.ToString() + " " +
t.Hour.ToString() + ":" + t.Minute.ToString() + ":" + t.Second.ToString() + "." +
t.Millisecond.ToString() + " ");
logWriter.WriteLine("After SerialCommRead(), status: " + status.ToString() + " bytesRead: " +
bytesRead[0].ToString());
logWriter.Flush();
}
}
The C++ code:
__declspec(dllexport) SERIAL_COM_STATUS SerialCommRead(HANDLE handle, unsigned char *buffer,
unsigned int length, unsigned int *bytesRead)
{
COMSTAT ComStat;
DWORD errorFlags, err;
*bytesRead = 0;
OVERLAPPED overlappedRead;
memset(&overlappedRead, 0, sizeof(OVERLAPPED));
overlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!overlappedRead.hEvent) {
err = GetLastError();
return(SER_COM_CREATE_EVENT_ERROR);
}
if (!ClearCommError(handle, &errorFlags, &ComStat)) {
err = GetLastError();
CloseHandle(overlappedRead.hEvent);
return(SER_COM_READ_ERROR);
}
if (!ComStat.cbInQue) {
CloseHandle(overlappedRead.hEvent);
return(SER_COM_OK); // There is nothing in queue to read
}
DWORD numOfBytesRead = 0;
if (!ReadFile(handle, (LPVOID)buffer, (DWORD)length, &numOfBytesRead, &overlappedRead)) {
err = GetLastError();
if (ERROR_IO_PENDING == err) {
DWORD res = WaitForSingleObject(overlappedRead.hEvent, SER_COM_OVERLAP_READ_TIMEOUT);
switch (res) {
case WAIT_OBJECT_0:
if (!GetOverlappedResult(handle, &overlappedRead, &numOfBytesRead, TRUE)) {
err = GetLastError();
CloseHandle(overlappedRead.hEvent);
return(SER_COM_GET_OVERLAP_ERROR);
}
break;
case WAIT_TIMEOUT:
*bytesRead = (unsigned int)numOfBytesRead;
CloseHandle(overlappedRead.hEvent);
return(SER_COM_TIMEOUT_ERROR);
case WAIT_FAILED:
err = GetLastError();
*bytesRead = (unsigned int)numOfBytesRead;
CloseHandle(overlappedRead.hEvent);
return(SER_COM_WAIT_ERROR);
default:
*bytesRead = (unsigned int)numOfBytesRead;
CloseHandle(overlappedRead.hEvent);
return(SER_COM_ERROR);
}
} else {
CloseHandle(overlappedRead.hEvent);
return(SER_COM_READ_ERROR);
}
}
CloseHandle(overlappedRead.hEvent);
*bytesRead = (unsigned int)numOfBytesRead;
PrintToFile("SerialCommRead(): going to return");
return(SER_COM_OK);
}
void PrintToFile(char *str)
{
struct _timeb timebuffer;
_ftime( &timebuffer );
char timeline[26];
ctime_s( timeline, 26, & ( timebuffer.time ) );
static FILE *fHandle = NULL;
if (NULL == fHandle)
{
// First time, open th file
fHandle = fopen(“test2.log”, "wt");
}
if (fHandle) {
fprintf(fHandle, "%.19s.%hu ", timeline, timebuffer.millitm);
fprintf(fHandle, "%s\n", str);
fflush(fHandle);
}
}
In file “test2.log” the printout of “SerialCommRead(): going to return” appears with a timestamp that is sometimes 5 seconds earlier than the printout to “test.log” from the C# code.
Looks like it takes the C++ function 5 seconds to return…
Any ideas?
Thanks,
Galit.