views:

1102

answers:

4

I have two threads that use an event for synchronization. In each thread they use the same call:

::CreateEvent( NULL,TRUE,FALSE,tcEventName )

The producer thread is the one that makes the call first, while the consumer thread makes the call last, so it's technically opening, not creating the event... I assume.

But, when SetEvent is called in the producer thread, the same event never gets triggered in the consumer thread (I'm using WaitForMultipleObjects())

Is there a tool that can tell me if the event is actually getting triggered properly.

Also, when I call CreateEvent() in each thread, the returned handle value is different for each... should they be the same?

Is there a better way to do this that will ensure it will work?

This is on Windows XP using Visual Studio 2005

Edit: I did some more checking and found that calling CreateEvent in the producer thread (the second one to call CreateEvent) sets LastError to 183 (ERROR_ALREADY_EXISTS), however CreateEvent still returns a handle to the event...what gives? How can it error as already existing but still return a handle? Or is it supposed to do that?

A: 

Your code should work as you've described it. If the event already exists when you try to create it, you will get a handle to the existing event.

Handles are different per-thread, so you needn't worry if they are different (they should be).

I suggest you simplify a little bit to see if things are working the way you expect. The fact that you're using WaitForMultipleObjects() tells me you have other stuff going on. If you think it's not working, get rid of the other stuff and see if you can figure it out.

SoapBox
See updated question...
Adam Haile
http://www.google.com/search?q=createevent <- first result
SoapBox
+1  A: 

If you just use several threads in one process, why don't you pass event handle from one to another? As I know named kernel objects created to share them between processes.

Also you can try to use OpenEvent function to open already created event. This might give some ideas.

begray
I tried using OpenEvent, but with the same results
Adam Haile
MSDN says that CreateEvent sets last error of ERROR_ALREADY_EXISTS exactly when it returns already existing handle. I'd check object names more carefully, maybe you're opening some other event? Or WaitForMultipleObjects call.
begray
Also I don't know for sure, but in my opinion event handle of the same event in different threads of one process should be equal. They may be different in different processes.
begray
A: 

In a single process you only have to call CreateEvent once and share the handle returned in all threads.

Also, you do not need to name the Event unless you want external processes to access the event with OpenEvent. In fact, if you name the event, only one copy of your program will be able to call CreateEvent successfully.

jmucchiello
+1  A: 

According to the MSDN documentation for CreateEvent,

If the function succeeds, the return value is a handle to the event object. If the named event object existed before the function call, the function returns a handle to the existing object and GetLastError returns ERROR_ALREADY_EXISTS.

Based on your description, I don't see a problem with what you're doing. There's nothing I see to indicate you're doing something incorrectly. For me, though, I usually create the event once using CreateEvent() and then pass the handle to the thread(s) that I want to be signaled by that event. But there is nothing technically wrong with your approach.

You do realize that WaitForMultipleObjects() returns the index of the first signaled handle in the handles array, right? For example, if your named event is the second one in the list, but the first handle is signaled the vast majority of the time (e.g., by a fast-acting thread or a manual reset event that is signaled but never reset), WaitForMultipleObjects() will always return WAIT_OBJECT_0. In other words, your consumer thread will never see the fact that your named event is signaled because the first handle is "always" signaled. If this is the case, put your named event first in the list.

You don't happen to have the bWaitAll parameter to WaitForMultipleObjects() set to TRUE, do you? If you do, then all of the handles in the handles array have be signaled before the function returns.

Who calls ResetEvent() for your named event? It should be the consumer. It's not accidentally being called by some third-party thread, is it?

These are simply some things to double-check. If the event still doesn't behave as you expect, replace the WaitForMultipleObjects() with WaitForSingleObject() to see if your named event properly signals the consumer thread.

Hope this helps.

Matt Davis