July 19, 2008
Chapter 7 Threading
Leroy Levin
What is a thread?
A thread in computer science is short for a thread of execution. Threads are a way for a program to fork (or split) itself into two or more simultaneously (or pseudo-simultaneously) running tasks. Threads and processes differ from one operating system to another but, in general, a thread is contained inside a process and different threads in the same process share some resources while different processes do not.
On a single processor, Multithreading generally occurs by time-division multiplexing ("time slicing") in very much the same way as the parallel execution of multiple tasks (computer multitasking): the processor switches between different threads. This context switching can happen so fast as to give the illusion of simultaneity to an end user. On a multiprocessor or multi-core system, threading can be achieved via multiprocessing, wherein different threads and processes can run literally simultaneously on different processors or cores.
Source: wikipedia ( one who knows all)
Threads vs. Processes - The key differences
Processes are:
- Typically independent
- Carry considerable state information
- Have separate address spaces
- Interact only through operating system supplied inter-process communication
Threads are:
- intimately tied to each other
- The CLR assigns each thread its own memory stack so that local variables are kept separate.
- Threads share (heap) memory with other threads running in the same application.
- one thread can be fetching data in the background, while another thread is displaying the data as it arrives.
- Each thread gets a data store isolated from all other threads. This is useful for storing "out-of band" data – that which supports the execution path's infrastructure, such as messaging, transaction or security tokens. Sometimes call Thread Local Storage
- Multithreading is managed internally by a thread scheduler
- Under Windows XP, a time-slice is typically in the tens-of milliseconds region – chosen such as to be much larger than the CPU overhead in actually switching context between one thread and another (which is typically in the few-microseconds region).
Threading Advantages:
- Compute intensive tasks can be handled in the back ground
- UI remains active while waiting for long running task
- A request/service broker can be developed where requests and services for those request can be handled concurrently
- Separate units of work that share memory space ( heap)
- One can fetch, one can write, one can display
- The applications work can be spread across multiple processors provided the operating system and runtimes support.
Disadvantages:
- Using multiple threads can lead to vastly more complex programs
- Having multiple threads does not in itself create complexity; it's the interaction between the threads that creates complexity. This applies whether or not the interaction is intentional, and can result long development cycles, as well as an ongoing susceptibility to intermittent and non-reproducible bugs.
- Requires thread context switch overhead to save of thread state
- Requires thread synchronization when shared data is accessed
- Any UI updates attempted by a non UI thread will cause exceptions
- A fatal exception on one thread takes the entire process down
System.Threading Namespace Classes
AbandonedMutexException, AutoResetEvent
CompressedStack, EventWaitHandle, ExecutionContext
HostExecutionContext, HostExecutionContextManager, Interlocked
LockRecursionException, ManualResetEvent, Monitor
Mutex, ReaderWriterLock, ReaderWriterLockSlim, RegisteredWaitHandle
RegisterWaitForSingleObject, Semaphore, SemaphoreFullException
SynchronizationContext, SynchronizationLockException, Thread
ThreadAbortException, ThreadExceptionEventArgs, ThreadInterruptedException
ThreadPool, ThreadStartException, ThreadStateException
Timeout, Timer, WaitHandle, WaitHandleCannotBeOpenedException
The System.Threading.Thread Class
Constructors
Name / Description/ Thread / Overloaded. Initializes a new instance of the Thread class.
Methods
Name / Description/ Abort / Overloaded. Raises a ThreadAbortException in the thread on which it is invoked, to begin the process of terminating the thread. Calling this method usually terminates the thread.
Furthermore, the exception will be re-thrown at the end of the catch block (in an attempt to terminate the thread for good) unless Thread.ResetAbort is called within the catch block. In the interim, the thread has a ThreadState of AbortRequested.
If the thread is not blocked Abort throws an exception on the thread right where it's executing – maybe not even in your code.
/ AllocateDataSlot / Allocates an unnamed data slot on all the threads. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
/ AllocateNamedDataSlot / Allocates a named data slot on all threads. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
/ BeginCriticalRegion / Notifies a host that execution is about to enter a region of code in which the effects of a thread abort or unhandled exception might jeopardize other tasks in the application domain.
/ BeginThreadAffinity / Notifies a host that managed code is about to execute instructions that depend on the identity of the current physical operating system thread.
/ EndCriticalRegion / Notifies a host that execution is about to enter a region of code in which the effects of a thread abort or unhandled exception are limited to the current task.
/ EndThreadAffinity / Notifies a host that managed code has finished executing instructions that depend on the identity of the current physical operating system thread.
/ Equals / Determines whether the specified Object is equal to the current Object. (Inherited from Object.)
/ Finalize / Releases all the resources used by the CriticalFinalizerObject class. (Inherited from CriticalFinalizerObject.)
In .NET Compact Framework3.5, this member is inherited from Object..::.Finalize()()().
In XNA Framework1.0, this member is inherited from Object..::.Finalize()()().
/ FreeNamedDataSlot / Eliminates the association between a name and a slot, for all threads in the process. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
/ GetApartmentState / Returns an ApartmentState value indicating the apartment state.
/ GetCompressedStack / Obsolete. Returns a CompressedStack object that can be used to capture the stack for the current thread.
/ GetData / Retrieves the value from the specified slot on the current thread, within the current thread's current domain. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
Thread local storage
/ GetDomain / Returns the current domain in which the current thread is running.
/ GetDomainID / Returns a unique application domain identifier.
/ GetHashCode / Returns a hash code for the current thread. (Overrides Object..::.GetHashCode()()().)
In .NET Compact Framework3.5, this member is inherited from Object..::.GetHashCode()()().
In XNA Framework1.0, this member is inherited from Object..::.GetHashCode()()().
/ GetNamedDataSlot / Looks up a named data slot. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
/ GetType / Gets the Type of the current instance. (Inherited from Object.)
/ Interrupt / Interrupts a thread that is in the WaitSleepJoin thread state.
If Interrupt is called on a thread that’s not blocked, the thread continues executing until it next blocks, at which point a ThreadInterruptedException is thrown.
/ Join / Overloaded. Blocks the calling thread until a thread terminates.
/ MemberwiseClone / Creates a shallow copy of the current Object. (Inherited from Object.)
/ MemoryBarrier / Synchronizes memory access as follows: The processor executing the current thread cannot reorder instructions in such a way that memory accesses prior to the call to MemoryBarrier execute after memory accesses that follow the call to MemoryBarrier.
/ ResetAbort / Cancels an Abort requested for the current thread.
/ Resume / Obsolete. Resumes a thread that has been suspended.
/ SetApartmentState / Sets the apartment state of a thread before it is started.
/ SetCompressedStack / Obsolete. Applies a captured CompressedStack to the current thread.
/ SetData / Sets the data in the specified slot on the currently running thread, for that thread's current domain. For better performance, use fields marked with the ThreadStaticAttribute attribute instead.
Thread local storage
/ SetProcessorAffinity / In the .NET Compact Framework for Xbox 360, sets the processor affinity for a managed thread. Processor affinity determines the processors on which a thread runs.
/ Sleep / Overloaded. Blocks the current thread for the specified number of milliseconds.
/ SpinWait / Causes a thread to wait the number of times defined by the iterations parameter.
/ Start / Overloaded. Causes a thread to be scheduled for execution.
/ Suspend / Obsolete. Either suspends the thread, or if the thread is already suspended, has no effect.
/ ToString / Returns a String that represents the current Object. (Inherited from Object.)
/ TrySetApartmentState / Sets the apartment state of a thread before it is started.
/ VolatileRead / Overloaded. Reads the value of a field. The value is the latest written by any processor in a computer, regardless of the number of processors or the state of processor cache.
/ VolatileWrite / Overloaded. Writes a value to a field immediately, so that the value is visible to all processors in the computer.
Properties
Name / Description/ ApartmentState / Obsolete. Gets or sets the apartment state of this thread.
/ CurrentContext / Gets the current context in which the thread is executing.
/ CurrentCulture / Gets or sets the culture for the current thread.
/ CurrentPrincipal / Gets or sets the thread's current principal (for role-based security).
/ CurrentThread / Gets the currently running thread.
/ CurrentUICulture / Gets or sets the current culture used by the Resource Manager to look up culture-specific resources at run time.
/ ExecutionContext / Gets an ExecutionContext object that contains information about the various contexts of the current thread.
/ IsAlive / Gets a value indicating the execution status of the current thread.
/ IsBackground / Gets or sets a value indicating whether or not a thread is a background thread.
/ IsThreadPoolThread / Gets a value indicating whether or not a thread belongs to the managed thread pool.
/ ManagedThreadId / Gets a unique identifier for the current managed thread.
/ Name / Gets or sets the name of the thread. You can set the name only once.
/ Priority / Gets or sets a value indicating the scheduling priority of a thread.
Priority levels of thread is set or checked by using an enumeration i.e. ThreadPriority. The valid values are for this enumeration are;
- Highest
- AboveNormal
- Normal
- BelowNormal
- Lowest
/ ThreadState / Gets a value containing the states of the current thread.
ExplicitInterfaceImplementations
Name / Description/ _Thread..::.GetIDsOfNames / Maps a set of names to a corresponding set of dispatch identifiers.
/ _Thread..::.GetTypeInfo / Retrieves the type information for an object, which can then be used to get the type information for an interface.
/ _Thread..::.GetTypeInfoCount / Retrieves the number of type information interfaces that an object provides (either 0 or 1).
/ _Thread..::.Invoke / Provides access to properties and methods exposed by an object.
Thread Delegates
_ ThreadStart / public delegate void ThreadStart(); no parameter allowed
ParameterizedThreadStart / public delegate void ParameterizedThreadStart (object obj);
Only a single parameter is allowed.
Thread States
ThreadState Enum members
Member name / DescriptionRunning / The thread has been started, it is not blocked, and there is no pending ThreadAbortException.
StopRequested / The thread is being requested to stop. This is for internal use only.
SuspendRequested / The thread is being requested to suspend.
Background / The thread is being executed as a background thread, as opposed to a foreground thread. This state is controlled by setting the Thread..::.IsBackground property.
Unstarted / The Thread..::.Start method has not been invoked on the thread.
Stopped / The thread has stopped.
WaitSleepJoin / The thread is blocked. This could be the result of calling Thread..::.Sleep or Thread..::.Join, of requesting a lock — for example, by calling Monitor..::.Enter or Monitor..::.Wait — or of waiting on a thread synchronization object such as ManualResetEvent.
Suspended / The thread has been suspended.
AbortRequested / The Thread..::.Abort method has been invoked on the thread, but the thread has not yet received the pending System.Threading..::.ThreadAbortException that will attempt to terminate it.
Aborted / The thread state includes AbortRequested and the thread is now dead, but its state has not yet changed to Stopped.
Background vs. foreground thread
- By default, threads are foreground threads, meaning they keep the application alive for as long as any one of them is running.
- C# also supports background threads, which don’t keep the application alive on their own – terminating immediately once all foreground threads have ended.
- Changing a thread from foreground to background doesn’t change its priority or status within the CPU scheduler in any way.
- A thread's IsBackground property controls its background status,
- When a background thread terminates, any finally blocks are circumvented.
- As circumventing finally code is generally undesirable, it's good practice to explicitly wait for any background worker threads to finish before exiting an application – perhaps with a timeout (this is achieved by calling Thread.Join)
- If for some reason a renegade worker thread never finishes, one can then attempt to abort it, and if that fails, abandon the thread, allowing it to die with the process (logging the conundrum at this stage would also make sense!)
- A common cause for an application failing to exit properly is the presence of “forgotten” foregrounds threads.
Thread Pool
- A thread pool economizes by coalescing many Wait Handles onto a few threads.
- To use the thread pool, you register a Wait Handle along with a delegate to be executed when the Wait Handle is signaled. This is done by calling ThreadPool.RegisterWaitForSingleObject,
- All pooled threads are background threads, meaning they terminate automatically when the application's foreground thread(s) end.
- However if one wanted to wait until any important jobs running on pooled threads completed before exiting an application, calling Join on the threads would not be an option, since pooled threads never finish!
- The idea is that they are instead recycled, and end only when the parent process terminates.
- Calling Abort on a pooled thread is Bad Idea. The threads need to be recycled for the life of the application domain.
Data Sharing ( AKA Locks) - Type of locks