views:

179

answers:

4

Hello,

I have a thread function on Process B that contains a switch to perform certain operations based on the results of an event sent from Process A, these are stored as two elements in an array.

I set the first element to the event which signals when Process A has data to send and I have the second element set to the event which indicates when Process A has closed.

I have began to implement the functionality for the switch statement but I'm not getting the results as I expect.

Consider the following:

//Thread function
        DWORD WINAPI ThreadFunc(LPVOID passedHandle)
        {    
            for(i = 0; i < 2; i++)
            {
                ghEvents[i] = OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("Global\\ProducerEvents"));
                if(ghEvents[i] == NULL)
                {
                    getlasterror = GetLastError();
                }
            }
            dwProducerEventResult = WaitForMultipleObjects(
                2,
                ghEvents,
                FALSE,
                INFINITE);

        switch (dwProducerEventResult) 
        {
        case WAIT_OBJECT_0 + 0: 
            {
                //Producer sent data
                //unpackedHandle = *((HWND*)passedHandle);

                MessageBox(NULL,L"Test",L"Test",MB_OK);
                break;
            }
        case WAIT_OBJECT_0 + 1:
            {
                //Producer closed
                ExitProcess(1);
                break;
            }
        default: 
            return;
        }

}

As you can see if the event in the first array is signalled Process B should display a simple message box, if the second array is signalled the application should close.

When I actually close Process A, Process B displays the message box instead.

If I leave the first case blank (Do nothing) both applications close as they should.

Furthermore Process B sends data an error is thrown (When I comment out the unpacking):

Error Image

Have I implemented my switch statement incorrectly? I though I handled the unpacking of the HWND correctly too, any suggestions?

Thanks for your time.

Edit:

The example I'm following: Here

Event creation in Process A:

for (i = 0; i < 2; i++) 
            { 
                ghEvents[i] = CreateEvent( 
                    NULL,   // default security attributes
                    TRUE,  // auto-reset event object
                    FALSE,  // initial state is nonsignaled
                    TEXT("Global\\ProducerEvents"));  // unnamed object

                if (ghEvents[i] == NULL) 
                { 
                    printf("CreateEvent error: %d\n", GetLastError() ); 
                    ExitProcess(0); 
                } 
        }
+2  A: 

Why are you opening the same event twice?

ghEvents[i] = OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("Global\\ProducerEvents"));

Shouldn't there be two different events?

This is consistent with the behavior you are reporting

When I actually close Process A, Process B displays the message box instead.

Because when you close process A the same event is signalled that enters the switch as WAIT_OBJECT_0 + 0

To sum up, create two different events - one for when process A is closing and the other to signal the message box to be shown.

The code below will only work for i <= 0 <= 9 But the main point is that the cycle iteration must create an event with a different name.

Process A:

LPTSTR eventName[] = _T("Global\\ProducerEventi");
for (i = 0; i < 2; i++) 
{ 
    eventName[20] = '0' - i; // this will change last i character with '0' or '1'
    ghEvents[i] = CreateEvent(NULL, TRUE, FALSE, eventName);
 ...

Process B:

LPTSTR eventName[] = _T("Global\\ProducerEventi");
for(i = 0; i < 2; i++)
{
    eventName[20] = '0' - i; // this will change last i character with '0' or '1'
    ghEvents[i] = OpenEvent(EVENT_ALL_ACCESS, FALSE, eventName);
    ...
smink
There is, as I mentioned I have an array of events. I've seen in the MSDN documentation that it can be done with an array of events and i've tried to stay faithful to their implementation.
Jamie Keeling
You have an array of events, true. Each position holds the same event also true. So when in process A you signal either event (always the same) you always end up in `WAIT_OBJECT_0 + 0`.
smink
I don't understand, I set each events individually in Process A for example, SetEvent(ghEvents[0]);.
Jamie Keeling
Events are identified by name. You gave the same name to both so, in practice, they are the same when seen by process B. Try appending an index - should be easy as you could use `for` index variable `i`.
smink
I've tried following the same technique in the MSDN article, I've added the link to it. I didn't realise mine was different.
Jamie Keeling
They are using a single event.
smink
Changed to code to reflect my previous comments and notes from answer.
smink
@smink: it looks a bit weird... Obviously, it does the job in the current situation, but it will not work for more than 10 events.
RaphaelSP
@Jamie: the MSDN example actually creates a single (named) event and several threads - and the wait is done on the threads, not the event.
RaphaelSP
@smink: Could you explain your snippet in a little bit more detail? I'm new to using events.
Jamie Keeling
@RaphaelSP Ah, my mistake.
Jamie Keeling
@RaphaelSP, you are right. The code will work for i <= 0 <= 9. But for the trivial example posted it works. Nevertheless the emphasized part is that the event name should change for each for iteration. Use _stprintf function for example.
smink
Excellent, thanks!
Jamie Keeling
+1  A: 

it is not about case/switch. you are trying to dereference invalid pointer.

Andrey
+1  A: 

It looks like you're trying to dereference a HWND, hence the crash.

Alex
+1  A: 

Assuming you're calling ThreadFunc like this:

ThreadFunc(hwndSomeWindow);

In which case, the cast should be:

unpackedHandle = (HWND) passedHandle;

Your code would have been right if the call were like this:

ThreadFunc(&hwndSomeWindow);
Adrian McCarthy
Excellent, thanks!
Jamie Keeling