Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Problems with overlapped Comms

Posted on 2002-05-28
5
909 Views
Last Modified: 2012-06-27
Hi there every one.
I have written my owm com port class (as my version of Builder does not come with it) which works fine with non-overlapped IO.
However, I need to continually test for incomming bytes and deal with them as and when.
Therefore I created a new thread where I pass the handle to an open comm port. In the execute function of the thread I have the following code.
The problem is that after the WaitCommEvent() returns the call to readfile returns immediatly with no byes read.
The call to GetLastError() returns the error "The parameter is incorrect."
While it is waiting for the WaitCommEvent() I can still send on the port using my original class in the main thread.
Any Ideas and help would be great, I have taken the day off to try and sort this problem out. :o/ <stumpped!>


for(;;) {
   if (WaitCommEvent(hCom, &dwCommEvent, NULL))
   {
  DWORD lpErrors;
  COMSTAT lpStat;
      do {
         if (ReadFile(hCom, &a, 1, &ByteCount, NULL))
                {   // A byte has been read; process it.
                *Str1 = *Str1 + chRead ;
                Form1->Memo1->Text = *Str1       ;//Memo1->Text + a;
                count++;
                }
                else
                {
                // An error occurred in the ReadFile call.
                LPVOID lpMsgBuf;
                FormatMessage(
                    FORMAT_MESSAGE_ALLOCATE_BUFFER |
                   FORMAT_MESSAGE_FROM_SYSTEM |
                   FORMAT_MESSAGE_IGNORE_INSERTS,
                   NULL,
                   GetLastError(),
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                   (LPTSTR) &lpMsgBuf,
                   0,
                   NULL
                );
                // Display the string.
                MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
                // Free the buffer.
                LocalFree( lpMsgBuf );

                ClearCommError(
                  hCom,     // handle to communications device
                  &lpErrors, // error codes
                  &lpStat  // communications status
                        );
                }
        } while (lpStat.cbInQue>0);//(ByteCount);
   }
   // A byte has been read; process it.
   else
   {
   }
}
0
Comment
Question by:dsch
  • 2
  • 2
5 Comments
 
LVL 3

Accepted Solution

by:
jlsjls earned 200 total points
ID: 7038678
You don't use overlapped I/O in your code.
You need to provide an overlapped structure to WaitForCommEvent. This structure contains an event object
which will be signaled when condition (see dwEvtMask) has occurred.
OVERLAPPED osReader;
memset(&osReader,0,sizeof(OVERLAPPED));
dwEvtMask =  EV_RXCHAR;          
SetCommMask(hPort, dwEvtMask);
if (!WaitCommEvent(hPort, &dwEvtMask, &osReader))
{
     dwError=GetLastError();
     if (GetLastError() == ERROR_IO_PENDING)
//overlapped I/O-operation cannot be completed immediately operation in background)                         {
          bWaiting = TRUE;
     }
     else if (dwError ==  ERROR_INVALID_HANDLE )
     {
           bKillThread = TRUE;
           continue;
     }
     else
     {
     wsprintf(szBuf,"WaitCommEvent Failed : Error %u",dwError);
     return(0);
     }
}
else {
  //read bytes from hPort
//In ReadFile call you need to use the overlapped structure
//used in WaitCommEvent()
//when all info has been processed, reset the event-object -> ResetEvent(osReader.hEvent );
}


Reamrk : hPort must be created in order to use OVERLAPPED I/O.
hPort = CreateFile(lpszPort,                               GENERIC_READ | GENERIC_WRITE,
          0,  
          NULL,                    OPEN_EXISTING,
          FILE_FLAG_OVERLAPPED, //overlapped I/O
     NULL );
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7038680
If you have opened the port using the FILE_FLAG_OVERLAPPED flag, then you must not pass NULL in the third parm to WaitCommEvent()

-- Dan
0
 
LVL 1

Author Comment

by:dsch
ID: 7038804
I think I've done what I should have done , but I still get the same result. (no bytes read)
Here is the revised version:

void __fastcall RS232RXThread::Execute()
{
DWORD ByteCount;
char a;
int count = 0;
bool Waiting = FALSE;
// Create the overlapped event. Must be closed before exiting
// to avoid a handle leak.
DWORD dwCommEvent=0;
DWORD dwCommMask = 0;

OVERLAPPED osReader;
memset(&osReader,0,sizeof(OVERLAPPED));
dwCommMask =  EV_RXCHAR;
SetCommMask(hCom, dwCommMask);

  DWORD lpErrors;
  COMSTAT lpStat;
  ByteCount = 1;
  LPVOID lpMsgBuf;
  osReader.hEvent = CreateEvent(
    NULL,   // no security attributes
    TRUE,  // auto reset event
    FALSE,  // not signaled
    NULL    // no name
    );

while(1) {
if(!Waiting)
{
   if (!WaitCommEvent(hCom, &dwCommEvent, &osReader))
   {

     if (GetLastError() == ERROR_IO_PENDING)
//overlapped I/O-operation cannot be completed immediately operation in background)
        {
         Waiting = TRUE;
        }

   }
}
else
{
if (dwCommEvent & EV_RXCHAR)
    {
       /*         ClearCommError(
                  hCom,     // handle to communications device
                  &lpErrors, // error codes
                  &lpStat  // communications status
                        );       */
        if(ReadFile(hCom, &a, 1, &ByteCount, NULL))  ;
        {
                   // A byte has been read; process it.
                *Str1 = *Str1 + a ;
                Form1->Memo1->Text = *Str1       ;//Memo1->Text + a;
                count++;
                Waiting = FALSE;
                dwCommEvent = 0;
                  // To do.
         }
    }
}// end else

}//end While
}//end of function
0
 
LVL 3

Expert Comment

by:jlsjls
ID: 7038825
In ReadFile you need to use overlapped structure 'osReader'
instead of NULL.
Also reset the event object. See my previous answer.
jlsjls
0
 
LVL 1

Author Comment

by:dsch
ID: 7038838
Yes, I just noticed that after I submitted.
It all works perfectly,
Thank you very much (and also DAN), I have learnt a lot today. Now I can get on with the rest of the app.
Thanks again
David :o]
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
FMX enumerated colours 2 115
How to convert MFC APP to Win32 APP. 19 94
passing data from one form to another form in c++ 27 83
FMX TCameraComponent Problem 2 84
Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

860 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question