It's a good idea to reuse a thread. (But remember that another option is to use the
thread pool.)
If you need a thread to be reused during the full time of the application, you can create one at the very beginning and throttle when it is not needed. What you need to do is to put it in a wait state. It switched a thread out and not scheduled back to execution until it is awaken, which happens on different conditions, in particular, timeout and abort. You can use the class
System.Threading.ManualResetEvent
:
http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx[
^].
When you put an event in a non-signaled state and some thread calls its
WaitOne
method, it will put the thread in a wait state, and awake that thread when the event is set signaled by some other thread. I hope you got the idea: you signal the event when you have some work for this thread to do.
See also my past answers on this topic:
ManualResetEvent and AutoResetEvent in Thread[
^],
pause running thread[
^].
You may need more high-level implementation of such mechanism. A well-known method of feeding tasks to a thread is a
blocking queue. You can find full source code and implementation in my article:
Simple Blocking Queue for Thread Communication and Inter-thread Invocation[
^].
With .NET 4.0, you can use
Concurrent.BlockingCollection
instead, please see the alternative to my article:
http://www.codeproject.com/script/Articles/ListAlternatives.aspx?aid=149540[
^].
Note that with .NET you can also feed the delegate instances and invoke them on the other thread as they are fed to the thread. This is the most advanced and easiest to use method of reusing threads. My article is complete with usage samples explaining the technique.
Also, it is very beneficial to use a thread via a
thread wrapper. Please see my past answers:
How to pass ref parameter to the thread[
^],
Change parameters of thread (producer) after it is started[
^],
MultiThreading in C#[
^].
Now, synchronization with the UI… Oddly enough, the mechanism is very similar to the solution with blocking queue, only the queue is non-blocking: this is the event queue of a UI thread. I'll explain:
You cannot call anything related to UI from non-UI thread. Instead, you need to use the method
Invoke
or
BeginInvoke
of
System.Windows.Threading.Dispatcher
(for both Forms or WPF) or
System.Windows.Forms.Control
(Forms only).
You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[
^],
Problem with Treeview Scanner And MD5[
^].
See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[
^],
Control events not firing after enable disable + multithreading[
^].
For other thread synchronization chores, use usual synchronization primitives. Remember though:
best synchronization is no synchronization. No, I'm not suggesting ignoring thread safety, never. Instead, you should design the code in as parallel way as possible: try to use functional style, do everything on stack, avoid static data, and so on. In other words, reduce the need for synchronization.
—SA