12.4 Summary
Computers perform multiple operations concurrently. Programming languages generally provide only a simple set of control structures that enable programmers to perform just one action at a time and proceed to the next action only after the previous one finishes. The FCL, however, provides the C# programmer with the ability to specify that applications contain threads of execution, where each thread designates a portion of a program that may execute concurrently with other threads. This capability is called multithreading.
A thread is initialized using the Thread class's constructor, which receives a ThreadStart delegate. This delegate specifies the method that contains the tasks a thread will perform. A thread remains in the Unstarted state until the thread's Start method is called, which the thread enters the Started state. A thread in the Started state enters the Running state when the system assigns a processor to the thread. The system assigns the processor to the highest-priority Started thread. A thread enters the Stopped state when its ThreadStart delegate completes or terminates. A thread is forced into the Stopped state when its Abort method is called (by itself or by another thread). A Running thread enters the Blocked state when the thread issues an input/output request. A Blocked thread becomes Started when the I/O it is waiting for completes. A Blocked thread cannot use a processor, even if one is available.
If a thread needs to sleep, it calls method Sleep. A thread wakes up when the designated sleep interval expires. If a thread cannot continue executing unless another thread terminates, the first thread, referred to as the dependent thread, calls the other thread's Join method to "join" the two threads. When two threads are joined, the dependent thread leaves the WaitSleepJoin state when the other thread finishes execution. When a thread encounters code that it cannot yet run, the thread can call Monitor method Wait until certain actions occur that enable the thread to continue executing. This method call puts the thread into the WaitSleepJoin state. Any thread in the WaitSleepJoin state can leave that state if another thread invokes Thread method Interrupt on the thread in the WaitSleepJoin state. If a thread has called Monitor method Wait, a corresponding call to Monitor method Pulse or PulseAll by another thread in the program will transition the original thread from the WaitSleepJoin state to the Started state.
If Thread method Suspend is called on a thread, the thread enters the Suspended state. A thread leaves the Suspended state when a separate thread invokes Thread method Resume on the suspended thread.
Every C# thread has a priority. The job of the thread scheduler is to keep the highest-priority thread running at all times and, if there is more than one highest-priority thread, to ensure that all equally high-priority threads execute for a quantum at a time in round-robin fashion. A thread's priority can be adjusted with the Priority property, which is assigned an argument from the ThreadPriority enumeration.