So after some heavy research into multi-threading and how to handle thread completion I have come across several solutions. Some solutions seem a lot more useful and informative than others. I would like to take some time to explain what I already know, and then in return, I would like to better understand why these solutions are implemented so variously. The original topic of this post was to discover the difference between Thread.Sleep(x)
and do {} while (b);
. From my understanding these two solutions are only different in the sense that Thread.Sleep(x)
will use less CPU than the latter. Spin waiting (empty while loop) will essentially run continiously from the CPU spiking percentages upwards of 85% which is a bad thing even on the fastest computers, I could only imagine what this would do to the average home computer.
Thread.Sleep
MSDN clearly states that when using Thread.Sleep(x)
the thread does not execute during the time specified.
The thread will not be scheduled for execution by the operating system for the amount of time specified.
There are other options recommended within the remarks section of Thread.Sleep(x)
such as using Timeout.Infinite
or Mutex
, Monitor
, Semaphore
, etc to synchronize threads and manage resources in a better manner. What is your opinion on this? Wouldn't this be just as bad as freezing the GUI with spin waiting?
MSDN also states that the since the system clock ticks at a specific rate called the clock resolution, the actual timing may not be the exact value specified since it is adjusted to coincide with clock ticks.
Spin Waiting
From my understanding this is an entirely bad practice. Once you initiate an empty loop it essentially blocks the thread it is executing it. This can result in freezing, crashing, and unresponsive GUIs, not to mention this can slow the user's computer down signifigantly since neither the compiler nor the operating system understand that the loop can be optimized to save uneccesary hits on performance. From my reading, the average computer can have between one and two cores of it's CPU running at 100% simply due to an empty while loop being executed continuously. The only effective usage of Spin Waiting that I've read about is thread synchronization. Have you used this to synchronize threads? I would imagine that there are better solutions and that using an empty loop would be problematic for debugging as well.
Background Worker
The BackgroundWorker
object has an event called RunWorkerCompleted
that is raised when the DoWork
event handler returns. In my experience with threading (which is minimal) I have always used this event to execute code once the threaded operation has completed. The biggest thing to take into account with this event is that if the background thread was canceled then you have no true way of knowing since the Canceled
flag will not be set to true if the CancellationPending flag has been set to true and missed by the polling loop. MSDN states it more thoroughly:
Be aware that your code in the DoWork event handler may finish its work as a cancellation request is being made, and your polling loop may miss CancellationPending being set to true. In this case, the Cancelled flag of System.ComponentModel.RunWorkerCompletedEventArgs in your RunWorkerCompleted event handler will not be set to true, even though a cancellation request was made. This situation is called a race condition and is a common concern in multithreaded programming. For more information about multithreading design issues, see Managed Threading Best Practices.
Final Thoughts
Since there are many ways to accomplish multiple tasks at the same time, which is generally considered best practice, why is it best practice, and what are the biggest differences between them all? I've put a lot of thought into this, and am highly curious about the advice of developers with more experience.
NOTES
I have dove deep into Google, MSDN, StackOverflow, and Daniweb, to put a good research effort into this question. The final thoughts area is the primary question set I would like to have answered. I believe the original post here was too broad and needed further information and clarity before I could recieve the answer I was truly looking for, and I apologize for taking so long to clarify my question.
Thank you all for your input!
-Jamie
DUPLICATE DIFFERENCE
In this post marked as duplicate to this one, the OP is requesting information on how to solve a problem with their BackgroundWorker
object not actually raising the RunWorkerCompleted
event, I am not having this issue, nor is my posting requesting information about this issue. My post is requesting detailed information on the difference between the three most common methods of waiting on a thread to complete before executing final operations. My main concern is the advantage and disadvantage to each solution as well as any further solutions that are considered common or best practice with multi-threading.