From: bicoman on


"Scott McPhillips [MVP]" wrote:

> bicoman wrote:
> >>>>I'm having a problem with my serial port routines that does not make any
> >>>>sense to me.
> >>>>I originally wrote the code to use non-overlapped serial port reading and
> >>>>writing. It works great. (the serial port anyway). The problem is the
> >>>>waitcommevent method hangs the program and it quits responding. Now for the
> >>>>weird part. When I go to overlapped io in CreateFile with
> >>>>FILE_FLAG_OVERLAPPED, my serial port stops reading. The program isn't hung
> >>>>anymore, and the connected device is definetly transmitting the appropriate
> >>>>bytes, the waitCommEvent function just quits seeing them. I know that
> >>>>WaitCommEvent is timing out because I checked. I've been fighting with this
> >>>>problem all day and am at my wits end. Has anyone ever had a similar problem?
> >>>
> >>Ian,
> >>Thanks for taking the time to respond to this. Here is my code
> >>...
>
> The basic problem is that you don't understand what overlapped I/O does.
> When you use it WaitCommEvent is supposed to "fail" and return
> quickly, with ERROR_IO_PENDING. This means the operation is continuing
> in the background. The purpose is to let your code do other things
> while waiting. But you are not doing "other things." Later, when the
> background operation has completed, the event in the overlapped struct
> will be signaled. But your code is not checking this event.
>
> It is also very inefficient and slow to wait for one character to be
> signaled, then call ReadFile to get the one character. The characters
> can arrive faster than an awkward program like this can process them.
> Instead, you can simply call ReadFile and it will return when it has the
> requested number of characters.
>
> Either of these approaches will, however, block the GUI thread, so the
> port should be read in a separate thread. I suggest you use the code
> from the MTTTY sample in MSDN. It shows how to very efficiently input
> from the serial port and send the results back to the main thread.
>
> --
> Scott McPhillips [VC++ MVP]
>
> Scott,
Thanks, I revised the code, it still is not detecting the event,
GetOverlappedResult only returns WAIT_TIMEOUT even though bytes have arrived.
Here is my newest attempt.

bool PickDialog::waitForAnswer(CString* answer){

BicoOutput* bco = new BicoOutput();
OVERLAPPED overlapped;
DWORD dwEventMask;
DWORD iBytesRead;
MSG msg;
HANDLE hCom;
bool readOnGoing = TRUE;
DWORD readResult;
DWORD dwRead;
char buffer[5];

ddata.getCommDefaults(&cp); //Get comm settings
commPort = sp.openPortForReading(cp); //openPort with
FILE_FLAG_OVERLAPPED
sp.clearCommErrors(commPort);

if(!SetCommMask(commPort,EV_RXCHAR))
AfxMessageBox("Failed to Set Communication Mask");

overlapped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
overlapped.Internal = 0;
overlapped.InternalHigh = 0;
overlapped.Offset = 0;
overlapped.OffsetHigh = 0;
assert(overlapped.hEvent);

while(readOnGoing){
readResult = WaitForSingleObject(overlapped.hEvent,READ_TIMEOUT);
switch(readResult){
case WAIT_OBJECT_0 + 1:
f(!GetOverlappedResult(commPort,&overlapped,&dwRead,FALSE)){

ReadFile(commPort,&buffer[0],MESSAGE_SIZE,&iBytesRead,&overlapped);
answer->Insert(0,&buffer[0]);
AfxMessageBox(*answer);
readOnGoing = FALSE;
break;
}
else{
AfxMessageBox("Error reading serial port in WaitForAnswer");
break;
}
case WAIT_TIMEOUT:
PeekMessage(&msg,NULL,0,0,PM_REMOVE);
if(msg.message == WM_LBUTTONDOWN){
AfxMessageBox("Exiting Pick");
pickOngoing = FALSE;
readOnGoing = FALSE;
}
break;
default:
AfxMessageBox("Error waiting to receive bytes in
WaitForAnswer");
}
}

sp.closePort(commPort);
ddata.~DefaultData();
return TRUE;


}

From: Ian Semmel on
Scott McPhillips suggested you look at the MTTTY sample in the documentation.

Did you do this ?

Get the sample working before you go any further.

bicoman wrote:
>
> "Scott McPhillips [MVP]" wrote:
>
>
>>bicoman wrote:
>>
>>>>>>I'm having a problem with my serial port routines that does not make any
>>>>>>sense to me.
>>>>>>I originally wrote the code to use non-overlapped serial port reading and
>>>>>>writing. It works great. (the serial port anyway). The problem is the
>>>>>>waitcommevent method hangs the program and it quits responding. Now for the
>>>>>>weird part. When I go to overlapped io in CreateFile with
>>>>>>FILE_FLAG_OVERLAPPED, my serial port stops reading. The program isn't hung
>>>>>>anymore, and the connected device is definetly transmitting the appropriate
>>>>>>bytes, the waitCommEvent function just quits seeing them. I know that
>>>>>>WaitCommEvent is timing out because I checked. I've been fighting with this
>>>>>>problem all day and am at my wits end. Has anyone ever had a similar problem?
>>>>>
>>>>Ian,
>>>>Thanks for taking the time to respond to this. Here is my code
>>
>> >>...
>>
>>The basic problem is that you don't understand what overlapped I/O does.
>> When you use it WaitCommEvent is supposed to "fail" and return
>>quickly, with ERROR_IO_PENDING. This means the operation is continuing
>>in the background. The purpose is to let your code do other things
>>while waiting. But you are not doing "other things." Later, when the
>>background operation has completed, the event in the overlapped struct
>>will be signaled. But your code is not checking this event.
>>
>>It is also very inefficient and slow to wait for one character to be
>>signaled, then call ReadFile to get the one character. The characters
>>can arrive faster than an awkward program like this can process them.
>>Instead, you can simply call ReadFile and it will return when it has the
>>requested number of characters.
>>
>>Either of these approaches will, however, block the GUI thread, so the
>>port should be read in a separate thread. I suggest you use the code
>>from the MTTTY sample in MSDN. It shows how to very efficiently input
>>from the serial port and send the results back to the main thread.
>>
>>--
>>Scott McPhillips [VC++ MVP]
>>
>>Scott,
>
> Thanks, I revised the code, it still is not detecting the event,
> GetOverlappedResult only returns WAIT_TIMEOUT even though bytes have arrived.
> Here is my newest attempt.
>
> bool PickDialog::waitForAnswer(CString* answer){
>
> BicoOutput* bco = new BicoOutput();
> OVERLAPPED overlapped;
> DWORD dwEventMask;
> DWORD iBytesRead;
> MSG msg;
> HANDLE hCom;
> bool readOnGoing = TRUE;
> DWORD readResult;
> DWORD dwRead;
> char buffer[5];
>
> ddata.getCommDefaults(&cp); //Get comm settings
> commPort = sp.openPortForReading(cp); //openPort with
> FILE_FLAG_OVERLAPPED
> sp.clearCommErrors(commPort);
>
> if(!SetCommMask(commPort,EV_RXCHAR))
> AfxMessageBox("Failed to Set Communication Mask");
>
> overlapped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
> overlapped.Internal = 0;
> overlapped.InternalHigh = 0;
> overlapped.Offset = 0;
> overlapped.OffsetHigh = 0;
> assert(overlapped.hEvent);
>
> while(readOnGoing){
> readResult = WaitForSingleObject(overlapped.hEvent,READ_TIMEOUT);
> switch(readResult){
> case WAIT_OBJECT_0 + 1:
> f(!GetOverlappedResult(commPort,&overlapped,&dwRead,FALSE)){
>
> ReadFile(commPort,&buffer[0],MESSAGE_SIZE,&iBytesRead,&overlapped);
> answer->Insert(0,&buffer[0]);
> AfxMessageBox(*answer);
> readOnGoing = FALSE;
> break;
> }
> else{
> AfxMessageBox("Error reading serial port in WaitForAnswer");
> break;
> }
> case WAIT_TIMEOUT:
> PeekMessage(&msg,NULL,0,0,PM_REMOVE);
> if(msg.message == WM_LBUTTONDOWN){
> AfxMessageBox("Exiting Pick");
> pickOngoing = FALSE;
> readOnGoing = FALSE;
> }
> break;
> default:
> AfxMessageBox("Error waiting to receive bytes in
> WaitForAnswer");
> }
> }
>
> sp.closePort(commPort);
> ddata.~DefaultData();
> return TRUE;
>
>
> }
>