Thread View: borland.public.cppbuilder.nativeapi
2 messages
2 total messages
Started by Lesley Anne
Tue, 08 Jul 2008 19:00
events and overlapped structures
Author: Lesley Anne
Date: Tue, 08 Jul 2008 19:00
Date: Tue, 08 Jul 2008 19:00
116 lines
5519 bytes
5519 bytes
I've been having trouble figuring out how to get events and overlapped
structures to work. This portion of our application connects to a named
pipe and reads from it. So long as there is data on the pipe to be read,
it works fine. We can connect and disconnect and re-connect again and
read whatever is there whenever we're connected. The problem comes when
there is no data on the pipe to be read. In our initial (non-overlapped)
version, it got stuck in the ReadFile function. This is why we went to
the overlapped structure, so that we could tell it to stop trying to read,
even if it hadn't read anything. But it doesn't seem to help. We still
get stuck trying to read, so I'm trying to figure out why our stop event
isn't working.
In our main unit, we have a global
HANDLE gbl_hStopEvent;
which is initialized in the main form's constructor as:
gbl_hStopEvent = CreateEvent(NULL, // default security attribute
TRUE, // manual reset event
FALSE, // initial state = not signaled
NULL); // not a named event object
We have a startup function that connects to a named pipe and then starts up
a reading thread:
pReadThread = new TReadThread(hReadPipe, gbl_hStopEvent);
When we want to close the connection we have a Cleanup function which
triggers the reading thread to terminate and sets that gbl_hStopEvent so
that the reading thread will get out of its WaitForMultipleObjects call
and see that it was terminated.
void Cleanup(void) {
pReadThread->Terminate();
SetEvent(gbl_hStopEvent);
FlushFileBuffers(hWritePipe);
//FlushFileBuffers(hReadPipe);
DisconnectNamedPipe(hReadPipe);
DisconnectNamedPipe(hWritePipe);
}
The problem is that the thread isn't seeing that gbl_hStopEvent. If it isn't
getting data to read, then it remains permanently stuck (presumably in its
WaitForMultipleObjects call). What's more, since that's using the read pipe,
the main unit is unable to DisconnectNamedPipe(hReadPipe) so then that gets
stuck as well.
Here's what the reading thread looks like:
// ---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "ReadThreadUnit.h"
#pragma package(smart_init)
// ---------------------------------------------------------------------------
__fastcall TReadThread::TReadThread(HANDLE hReadPipe, HANDLE hStopEvent)
: TThread(false)
{
ReadPipeHandle = hReadPipe;
StopEventHandle = hStopEvent;
}
// ---------------------------------------------------------------------------
void __fastcall TReadThread::Execute()
{
DWORD cbBytesRead=0 ;
BOOL Success;
OVERLAPPED op;
HANDLE HandleArray[2];
bool bStop=false;
memset(&op, 0, sizeof(op));
HandleArray[0] = op.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
HandleArray[1] = StopEventHandle;
ResetEvent(StopEventHandle);
while (!Terminated && !bStop) {
Success = ReadFile(ReadPipeHandle, szReadRequest, READ_BUFSIZE,
&cbBytesRead, &op);
if (Success) {
szReadRequest[cbBytesRead] = 0;
if (cbBytesRead)
Synchronize(SendReadMessage);
else Synchronize(SendReadError);
}
else {
if (GetLastError() == ERROR_IO_PENDING) {
SetLastError(0);
switch (WaitForMultipleObjects(2, HandleArray, FALSE, INFINITE)) {
case WAIT_OBJECT_0:
Success = GetOverlappedResult(ReadPipeHandle, &op,
&cbBytesRead, FALSE);
if (Success) {
szReadRequest[cbBytesRead] = 0;
Synchronize(SendReadMessage);
}
else
Synchronize(SendReadError);
ResetEvent(HandleArray[0]);
break ;
case WAIT_OBJECT_0+1:
bStop = true;
break;
}
}
else Synchronize(SendReadError);
}
}
}
// ---------------------------------------------------------------------------
void __fastcall TReadThread::SendReadMessage() {
Form1->HandleReadMessage(szReadRequest) ;
}
// ---------------------------------------------------------------------------
void __fastcall TReadThread::SendReadError() {
Form1->HandleReadErrors() ;
}
// ---------------------------------------------------------------------------
Re: events and overlapped structures
Author: Remy Lebeau (TeamB)
Date: Tue, 08 Jul 2008 20:05
Date: Tue, 08 Jul 2008 20:05
63 lines
3236 bytes
3236 bytes
"Lesley Anne" <mspfila (dash) brl (at) yahoo (dot) com> wrote in message news:4873b98e$1@newsgroups.borland.com... > In our initial (non-overlapped) version, it got stuck in the ReadFile > function. You could use PeekNamedPipe() to avoid that. > This is why we went to the overlapped structure, so that we could tell it > to stop trying to read, even if it hadn't read anything. Are you openng the pipe in overlapped mode to begin with? You can only pass an OVERLAPPED structure to ReadFile() if the pipe has the FILE_FLAG_OVERLAPPED flag enabled. > We still get stuck trying to read Then you are not using overlapped I/O correctly. > so I'm trying to figure out why our stop event isn't working. Is you code getting into WaitForMultiObjects() to begin with? Or is it getting stuck in ReadFile()? > pReadThread = new TReadThread(hReadPipe, gbl_hStopEvent); How are you creating hReadPipe exactly? > When we want to close the connection we have a Cleanup function > which triggers the reading thread to terminate and sets that > gbl_hStopEvent > so that the reading thread will get out of its WaitForMultipleObjects > call and see that it was terminated. Only if it reaches WaitForMultipleObjects() to begin with. > The problem is that the thread isn't seeing that gbl_hStopEvent. If it > isn't getting data to read, then it remains permanently stuck > (presumably in its WaitForMultipleObjects call). Don't presume anything. Debug your code and find out exactly where it is getting stuck. > What's more, since that's using the read pipe, the main unit is > unable to DisconnectNamedPipe(hReadPipe) so then that gets > stuck as well. Wait until the thead terminates before you disconnect. > ResetEvent(StopEventHandle); I would not do that inside the thread. What if you want to terminate the thread before it begins running? Your main thread would signal the event, and then the thread would reset it and continue running. Since the event is created intially unsignaled, there is no need for the thread to reset it. > ResetEvent(HandleArray[0]); You don't need to do that. ReadFile() will handle that for you. Gambit
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads