views:

335

answers:

1

I have a global event created and set/reset in a native C++ process that are created like this:

HANDLE hGlobalEvent = CreateEvent(NULL, TRUE, FALSE, _T("Global\\MyEvent"));

Is there any way (even if it's with a library not written by MS) to register for one of these events in a .NET (C#) process so that I standard .NET events handlers are fired off when the global event changed?
And I don't really just want to wait on the event and loop, as is the way in C++ with WaitForSingleObject...I really would like it to be a completely asynchronous event handler.

I've got to imagine there's an easy way to do this...just can't find it.

+1  A: 

ThreadPool.RegisterWaitForSingleObject can be used to execute a callback when the event is signalled. Obtain a WaitHandle for the named event object by using the EventWaitHandle constructor that takes a string name.

bool createdNew;
WaitHandle waitHandle = new EventWaitHandle(false,
    EventResetMode.ManualReset, @"Global\MyEvent", out createdNew);
// createdNew should be 'false' because event already exists
ThreadPool.RegisterWaitForSingleObject(waitHandle, MyCallback, null,
    -1, true);

void MyCallback(object state, bool timedOut) { /* ... */ }
Bradley Grainger
EventWaitHandle will be opening the event created in the Win32 process, not creating a new event, correct?
Adam Haile
Yes, and there's an overload of the constructor you can call to verify this; it has an 'out' bool parameter that tells you whether the event already existed or was created by the constructor. In your case, the out value should be false. I've updated the code snippet to show this.
Bradley Grainger
Awesome...thanks for the update. This has really helped. And now, maybe a solution to this question will actually show up on google :)
Adam Haile
Ok...this sort of works. The problem is that I need to know the actually state of the event and all this does is give me what I passed in for the third param in RegisterWait. Also, if I leave the last param as true, it only fires once and I have to keep re-registering, but if I set it to false, it just endlessly calls the callback once the state of the event changed... though I still don't know what that state is...
Adam Haile
To clarify a bit more...in C++ a Wait on an event only returns when the events state is changed to "signaled" (true), but not when it's changed back to unsignaled (false)... therefore you inherently know the state. You can also call wait with a 0 timeout and if it returns WAIT_OBJECT the state is true and if WAIF_TIMEOUT it's false. But this C# code seems to run the callback whenever the state changes at all....
Adam Haile
In the original code you gave, the second argument to CreateEvent is TRUE, indicating that it's a manual-reset event. Unless the event is reset, the callback will keep getting executed because the underlying event is still signaled. If it's the callback's responsibility to reset the event, then call 'waitHandle.Reset()' in MyCallback. If you're expecting someone else to reset the event, I'm not sure of a good way to execute the callback only once until the event is reset, then set again.
Bradley Grainger
Understood...I realized that. Fortunately, what I had left out of the original code was that there were actually two events, one for Connect and one for Disconnect (it's watching for a USB bar code scanner). So what I ended up doing was checking the initial state of both at startup, then watching for the unsignaled one, and alternating to the other event when that one was signaled. Switching back and forth solved my problem.Thanks for the help!
Adam Haile