What is difference between Thread.Join and waitHandle.WaitOne()? - c#

Thread.Join and waitHandle.WaitOne(), both of them force the calling thread to wait. Until the thread has finished executing and until the waitHandle.Set() is called respectively.
But is there any difference between the 2 besides this?

...both of them force the calling thread to wait until the called
thread has finished executing.
No, they don't. They are completely different.
WaitHandle.WaitOne will block the calling thread until the wait handle is signaled.
Thread.Join will block the calling thread until the thread object which the Join method is called is finished executing(terminated)

#helloworld, A distinction is "at the end of the method". Unless your method catches all exceptions, it may exit due to unhandled exception (e.g. due to thread.abort), before your call to WaitHandle.Set().
WaitHandles require cooperation/knowledge between threads. The called thread has to be passed the wait handle, and it has to signal at the appropriate time. It is useful, when two threads are sharing a resource such as a pub-sub queue.
WaitHandles are just one of many signaling/locking mechanisms. Semaphores, mutexes, lock files and even thread-shared variables (accessed carefully, e.g. Interlocked.Increment) can be used for signaling.
Thread.Join - does not require any cooperation from the called thread. When the called thread is done for any reason, including abnormal termination, join returns.
Thread.Join is more like Process.Wait. Process.Wait returns when the process terminates for any reason.
In short, if you need to know when a thread terminates for any reason, use Thread.Join.
When you need to know if a thread has executed to a certain point, use signaling.

Related

Is it safe to call .Close (.Dispose) on an EventWaitHandle directly after .Set?

I have one thread waiting on an EventWaitHandle (AutoResetEvent):
AutoResetEvent.WaitOne();
I have another thread signalling the first thread to continue
AutoResetEvent.Set();
AutoResetEvent.Close();
Is it safe to call .Close direct after .Set, in other words will it be guaranteed that the waiting thread has continueed before the AutoResetEvent is disposed?
Yes, it is safe if things work out exactly as described in your question. If you know that all threads were already waiting when you called set, those threads will have been signaled and everything will be fine since all threads that are waiting are guaranteed to be released before a call to set returns.
However, if you for some reason experience a race and call set and close before the thread has started to wait you will get a exception when trying to wait. So in practice you are better off avoiding this pattern. IMHO

Why does Control.Invoke() calls PostMessage() instead of SendMessage()?

Control.Invoke() calls PostMessage() and then waits until the UI thread finishes processing the message. So why it does not calls SendMessage() instead (which by default waits until the UI thread finishes processing the message).
Control.Invoke() is a dangerous method, many .NET programmers have deadlocked their program with it. It should be very strongly avoided because of this. Simple everyday operations like closing a window become perilous. You'll want to wait until a worker thread cannot invoke anymore since nothing good happens when the thread keeps running but the UI is gone. So you signal the thread with, say, AutoResetEvent and wait for it to complete.
Such a wait is very likely to deadlock your program when the thread is calling Invoke() at just the wrong time. The thread cannot complete because it is stuck in the Invoke() call, the UI thread cannot service it since it is stuck in the wait. A "deadly embrace", neither thread can make progress and your program will hang. Quite hard to debug since it is not predictable and doesn't happen often enough, only goes wrong when the thread calls Invoke at exactly the same time.
Breaking that deadlock requires knowing that an Invoke() call is in progress so it can be cancelled. It is not knowable when you use SendMessage(). The lock on which it blocks is hidden in the OS. I've recently posted an answer about the problems with SendMessage, everything you read there applies here as well.
So Microsoft did not implement it that way and they use PostMessage. They add an entry to the invoke queue, call PostMessage to wake up the UI thread so it goes looking through that queue. And specific to Invoke over BeginInvoke, they block on a ManualResetEvent in the queue entry, signaled when the UI thread completed the call to the delegate target.
Now they can do something to avoid the deadlock, when a window closes it looks through the invoke queue and cancels any that had that window as the invoke target. Or in other words, the lock that's invisible when you use SendMessage and causes deadlock now becomes visible and can be released to break the deadlock.

Timing of thread transition from Unstarted to Running

"An Unstarted thread is transitioned into the Running state by calling Start." [from msdn ThreadState enumeration docs.
Exactly when does a thread transition from Unstarted to Running?
If I instantiate a thread and call Start, is there a delay before the thread actually moves to Running? If the instantiating thread calls Join immediately after Start, is there a risk it'll catch the new thread in an Unstarted state?
Its state becomes Running before the Start() method returns, though it may not yet (and quite often will not) have done any actual work, as it may not yet have been given any core time. Most of the time the fact that we can think of the tread as running is enough (just as most of the time we can think "we have 6 threads running" when if we only have 4 cores the obviously we've only got up to 4 actually doing something). It could also be that by the time you get to the next instruction on the calling thread, that it's WaitSleepJoin or even Stopped but it won't be Unstarted.
It's perfectly safe to call Join() even in the very next statement after Start() (though that would rarely be useful).
The call to Start isn't asynchronous, so the method would return with the thread started. I've done this in a few sample apps and calling Join immediately afterwards never caused any problems.
The documentation for ThreadState.Unstarted states
Unstarted The Thread::Start method has not been invoked on the thread.
In other words, no, you can't end up with Thread.Unstarted after Thread::Start has been called. The Thread is not guaranteed to be in ThreadState.Running though, it could be in for example ThreadState.WaitSleepJoin if it blocks on a Mutex before you check the state.
The only ThreadState that causes problems with Join is ThreadState.Unstarted though, so calling Join is safe right after Start, provided Start does not throw an exception.

AutoResetEvent and COM Objects

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:
(UI) New thread spawned
(UI) Code calls WaitOne(); timeout: 10s
(T2) Thread opens device, calls Set()
(UI) WaitOne blocks message loop
(UI) WaitOne timeout elapsed, code execution continues
(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.
... 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.
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):
New Thread Spawned
a. Original thread calls WaitOne(); b. New thread calls Set();
Original thread wakes up.
Original thread calls Reset();
You might find this SO post on "Waiting on the mainthread while continuing to process"
Also checkout Calling Synchronous Methods Asynchronously from MSDN

Thread, abort and wait

I am aborting a thread (will be threads soon enough) and the problem is i need to stall until all threads have been aborted.
After doing the Thread.Abort(); I thought of using the Thread.Join() to wait until its been fully aborted. However that doesnt work. It just waits forever. How can i abort each thread and wait until its done before continuing?
Additional information: If your curious why - in this case I am closing a window, I pass a delegate func into the thread which it calls when its done (or aborted). If I dont stall then the window will close and the function will call invalid handles/objs. I can easily use the same method, stick a flag in and loop & sleep until all flags are set but that doesnt feel right.
I've learnt from many years experience with threads that there are a couple of rules that, if followed, make life a lot easier.
The one pertinent to this question is:
let threads control their own resources, including their lifetime.
I wouldn't abort a thread, I'd simply set up a communications method between the threads creator and the thread itself to signal the thread to terminate, and then let the thread itself shut down.
This method can often be as simple as a write-by-creator/read-by-thread flag which controls the threads main loop. If the thread has long running tasks while in the loop, you should also check periodically.
Then the creator thread should just join until the thread exits. Properly designed, you can set an upper limit to the time this will take.
Use a synchronisation object such as an Event. For example, each background thread has an Event associated with it. When the thread is terminating, it signals the Event. The main thread does a WaitHandle.WaitAll on the set of Events, and proceeds only when all Events are signalled.
Be warned that if there is a chance that the background threads will take a long time to terminate, blocking the main thread while waiting for them would create a bad user experience. So if this is the case, you may want to hide the window before blocking. Also, you'll want to test what the impact of this is on your callback delegate -- if the UI thread is blocked in a wait, will it be able to handle your delegate?
Might not a better design be not to call the delegate if the thread is being killed due to the window closing? Just have the main thread tell the background threads why they are terminating and have them skip the callback if the reason is "window closing." (This assumes that you are communicating with the threads, as Pax rightly recommends, rather than just calling Abort.)

Categories