views:

179

answers:

3

I've noticed that AutoResetEvent completely freezes the message loop (sometimes) when in the middle of a WaitOne() call, effectively even blocking the signal message.

IE:

  1. (UI) New thread spawned
  2. (UI) Code calls WaitOne(); timeout: 10s
  3. (T2) Thread opens device, calls Set()
  4. (UI) WaitOne blocks message loop
  5. (UI) WaitOne timeout elapsed, code execution continues
  6. (UI) Main window receives signal and continues (but WaitOne failed)

Any ideas?

EDIT: added UI/T2's to specify threads. Also, I'm trying to turn a 3rd party library to synchronous. Opening devices involves an Open() call that in turn spawns an OpenOK or OpenFailed event, I'm trying to make a bool Open() call that returns true/false depending on which event was spawned.

A: 

This is the result of a race condition. The problem is that step 3 might be happening before step 2 because they're on different threads. Because you're using an AutoResetEvent, by the time WaitOne is called, the event is already reset.

Because of this problem, whenever possible, I generally try to avoid AutoResetEvents in favor of ManualResetEvents.

The order of events with a ManualResetEvent would be (I've listed event 2 as 2a and 2b to demonstrate that their order of operation is not guaranteed):

  1. New Thread Spawned
  2. a. Original thread calls WaitOne(); b. New thread calls Set();
  3. Original thread wakes up.
  4. Original thread calls Reset();
Kennet Belenky
It's not a race condition though. In the particular case I've been testing, it's not immediate - it takes a couple seconds. Either way, how would this change w/ ManualResetEvent instead of Auto?
hb
The delay does not contra-indicate the race condition that I see.ManualResetEvents will remain set until they are explicitly reset. Your AutoResetEvent is resetting itself before the WaitOne is called. That's why the WaitOne is never triggered.
Kennet Belenky
Same issue occurs with ManualResetEvent. I know for sure that the message pump is being blocked too, but I don't know how to deal with this. :(
hb
@Kennet - According to MSDN, AutoResetEvent remains signaled until a single waiting thread is released, and then automatically returns to the non-signaled state. If no threads are waiting, the state remains signaled indefinitely.If a thread calls WaitOne while the AutoResetEvent is in the signaled state, the thread does not block. The AutoResetEvent releases the thread immediately and returns to the non-signaled state.So it wont reset until there is the call to WaitOne (in which case it it was Set before hand, it should not block); there is something else going on.
SwDevMan81
@SwDevMan81 - You appear to be correct. I was barking up the wrong tree there.
Kennet Belenky
A: 

You might find this SO post on "Waiting on the mainthread while continuing to process"
Also checkout Calling Synchronous Methods Asynchronously from MSDN

SwDevMan81
+1  A: 

... effectively even blocking the signal message.

You can't "block a signal" from being sent, you can only prevent the other thread from getting to the point of setting the event. Wait handles do not require a message pump at all.

The only thing I can think of may be that the COM object in question is tied to the UI thread. Accessing the COM object may be attempting to invoke back from T2 to the UI thread which is waiting for T2 to do something (deadlock). To see if this is indeed the problem make sure you are not creating or accessing the COM object on the UI thread.

csharptest.net
What if I *have* to create it on the UI thread? What would you recommend? Likewise, how would you create it on another thread?
hb
Couple of options... easy answer is to use only the UI thread and a Timer event to poll the COM object until complete.
csharptest.net