Threading in C#
An extensive article on multithreading in C#. This tackles difficult issues such as thread safety, when to use Abort, Wait Handles vs Wait and Pulse, the implications of Apartment Threading in Windows Forms, using Thread Pooling, Synchronization Contexts, Memory Barriers and non-blocking synchronization constructs.
C# supports parallel execution of code through multithreading. A thread is an independent execution path, able to run simultaneously with other threads. A C# client program (Console, WPF, or Windows Forms) starts in a single thread created automatically by the CLR and operating system (the ‘main’ thread), and is made multithreaded by creating additional threads.
Multithreading is managed internally by a thread scheduler, a function the CLR typically delegates to the operating system. A thread scheduler ensures all active threads are allocated appropriate execution time, and that threads that are waiting or blocked (for instance, on an exclusive lock or on user input) do not consume CPU time.
On a single-processor computer, a thread scheduler performs time-slicing – rapidly switching execution between each of the active threads. Under Windows, a time-slice is typically in the tens-of-milliseconds region – much larger than the CPU overhead in actually switching context between one thread and another (which is typically in the few-microseconds region).
On a multi-processor computer, multithreading is implemented with a mixture of time-slicing and genuine concurrency, where different threads run code simultaneously on different CPUs. It’s almost certain there will still be some time-slicing, because of the operating system’s need to service its own threads – as well as those of other applications.
A thread is said to be preempted when its execution is interrupted due to an external factor such as time-slicing. In most situations, a thread has no control over when and where it’s preempted.