As most of you correctly highlighted, the last exercise exhibits a deadlock situation. The main thread here simply creates and starts another thread and waits for its completion, but this expectation is never fulfilled.
class Program { static void Main(string[] args) { var workerThread = new Thread(Worker); workerThread.Start(); workerThread.Join(); } ...
When one looks at the worker thread code, you realize that the stopping condition is never going to be met: Thread.CurrentThread.IsAlive just cannot be false! The current thread is alive, otherwise it will be dead, hence not executing code.
... static void Worker() { while (Thread.CurrentThread.IsAlive) { Console.Write("Blah"); } } }
Based on a true story, this example shows a very common misconception, that the framework provides facilities to control the life cycle of threads, and for that matter that Join will trigger a graceful stop. Well, sorry to break this to you guys, this is just not happening. It is your responsibility to implement an appropriate mechanism.
Here is a valid implementation using a shared flag:
public class Solution { private readonly object synchro = new object(); private bool run; static void Main(string[] args) { var workerThread = new Thread(Worker); run = true; workerThread.Start(); lock (this.synchro) { run = false; } // wait for the thread to start workerThread.Join(); } private void Worker() { for (;;) { lock (this.synchro) { if (!run) { break; } } Console.Write("Blah "); } } }
New! Available on GitHub: for the curious, the critics and the laziest, I have but the code on GitHub as a VS 2012 solution.
Related articles
- Can you spot the deadlock 4 ?! (dupdob.wordpress.com)