Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

events and overlapped structures

26 views
Skip to first unread message

Lesley Anne dash at dot

unread,
Jul 8, 2008, 3:00:18 PM7/8/08
to
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() ;
}
// ---------------------------------------------------------------------------


Remy Lebeau (TeamB)

unread,
Jul 8, 2008, 4:05:50 PM7/8/08
to

"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


0 new messages