Most interaction with the
System.Threading
namespace occurs via the Thread type. This type
encapsulates most of the logic needed to control the way threads
behave.
The most commonly used static methods, usually
referred to as thread relative statics, are
methods and properties that refer to the currently executing thread.
Sleep( ) causes the calling thread to sleep for a
specified amount of time. If for some reason the thread gets woken
up, a ThreadInterruptedException is thrown.
Because this method can only be called by the current thread and not
on a reference to a thread that may also be executing, the thread
sleeps immediately and does not need to wait for a safe point for
garbage collection as the Suspend( ) method does
(see later in this entry).
GetData( ) retrieves data from a
specified slot in thread local
storage. To use this method, slots need to be initialized
already (see later in this section). SetData( )
stores data in thread local storage to be
retrieved using GetData( ).
AllocateDataSlot( ) and
AllocateNamedDataSlot( ) allocate a data slot for
use with the previous two methods.
The Thread class also provides the static property
CurrentThread, which returns a reference to the
Thread object for the currently running thread.
The current thread can then access any of the following instance
methods or properties on itself: Abort( ) causes a
thread to abort, throwing a ThreadAbortException
and executing any finally blocks. You may catch
the ThreadAbortException, but it is automatically
rethrown unless you invoke ResetAbort( ), which
countermands the Abort( ) and lets the thread
continue to live. Interrupt( ) interrupts a thread
that is in the ThreadState.WaitSleepJoin state. If
a thread is not in the ThreadState.WaitSleepJoin
state, it is interrupted when it next attempts to enter that state
(Join( ) causes the calling thread to enter that
state). The calling thread only starts again once the referenced
thread finishes executing and enters the
ThreadState.Stopped state. Suspend(
) suspends a thread. The thread is suspended once it has
reached a safe point for garbage collection. The current thread can
then access any of the following instance methods or properties on
itself. Resume( ) resumes a thread that is in the
suspended state. Threads in the suspended state are resumed
regardless of how many times Suspend( ) was
called. Start( ) tells a thread to start
executing.
Starting with .NET 1.1, the Thread class provides
three new methods (with appropriate overloads) that allow for direct
access without respect to any per-processor or per-thread inherent
caching mechanism; the VolatileRead( ) and
VolatileWrite( ) methods will fetch and set
"the value of a field... the latest written by any
processor in a computer, regardless of the number of processors or
the state of the processor cache" (from the MSDN
documentation). This bears some explanation to make sense. Each CPU
within the CLR, in the interests of efficiency, is allowed to cache
values of objects and data within a thread-local cache, so that
requests to access those fields doesn't require a
full trip out to the garbage-collected heap. Unfortunately, doing so
tends to lead to situations where multiple threads accessing the same
fields on the same object (since these values are cached on a per-CPU
basis) lead to different values across threads executing on those
different CPUs, which is obviously a bad idea. Normally, by using the
lock block within C#, a memory barrier is set up,
meaning the thread is now required to synchronize its processor cache
with the global heap settings, thus forcing the processor-cached
field values to match what's in the global heap.
These methods (VolatileRead( ) and
VolatileWrite( )) force a trip out to the heap,
rather than relying on processor cache, useful in situations where an
explicit lock is not desired, yet accurate
reflection of the object's state is necessary. In
addition, the MemoryBarrier( ) method provides the
same flushing of cache data to the central heap, but again, this same
behavior is seen when using the lock syntax or the
Monitor class, both of which provide the same
semantics but are clearer and easier to use. For the most part,
programmers are encouraged to use lock and/or
Monitor where accessing shared data across
threads.
public sealed class Thread {
// Public Constructors
public Thread(ThreadStart start);
// Public Static Properties
public static Context CurrentContext{get; }
public static IPrincipal CurrentPrincipal{set; get; }
public static Thread CurrentThread{get; }
// Public Instance Properties
public ApartmentState ApartmentState{set; get; }
public CultureInfo CurrentCulture{set; get; }
public CultureInfo CurrentUICulture{set; get; }
public bool IsAlive{get; }
public bool IsBackground{set; get; }
public bool IsThreadPoolThread{get; }
public string Name{set; get; }
public ThreadPriority Priority{set; get; }
public ThreadState ThreadState{get; }
// Public Static Methods
public static LocalDataStoreSlot AllocateDataSlot( );
public static LocalDataStoreSlot AllocateNamedDataSlot(string name);
public static void FreeNamedDataSlot(string name);
public static object GetData(LocalDataStoreSlot slot);
public static AppDomain GetDomain( );
public static int GetDomainID( );
public static LocalDataStoreSlot GetNamedDataSlot(string name);
public static void MemoryBarrier( );
public static void ResetAbort( );
public static void SetData(LocalDataStoreSlot slot, object data);
public static void Sleep(int millisecondsTimeout);
public static void Sleep(TimeSpan timeout);
public static void SpinWait(int iterations);
public static byte VolatileRead(ref byte address);
public static double VolatileRead(ref double address);
public static short VolatileRead(ref short address);
public static int VolatileRead(ref int address);
public static long VolatileRead(ref long address);
public static IntPtr VolatileRead(ref IntPtr address);
public static object VolatileRead(ref object address);
public static sbyte VolatileRead(ref sbyte address);
public static float VolatileRead(ref float address);
public static ushort VolatileRead(ref ushort address);
public static uint VolatileRead(ref uint address);
public static ulong VolatileRead(ref ulong address);
public static UIntPtr VolatileRead(ref UIntPtr address);
public static void VolatileWrite(ref byte address, byte value);
public static void VolatileWrite(ref double address, double value);
public static void VolatileWrite(ref short address, short value);
public static void VolatileWrite(ref int address, int value);
public static void VolatileWrite(ref long address, long value);
public static void VolatileWrite(ref IntPtr address, IntPtr value);
public static void VolatileWrite(ref object address, object value);
public static void VolatileWrite(ref sbyte address, sbyte value);
public static void VolatileWrite(ref float address, float value);
public static void VolatileWrite(ref ushort address, ushort value);
public static void VolatileWrite(ref uint address, uint value);
public static void VolatileWrite(ref ulong address, ulong value);
public static void VolatileWrite(ref UIntPtr address, UIntPtr value);
// Public Instance Methods
public void Abort( );
public void Abort(object stateInfo);
public void Interrupt( );
public bool Join(int millisecondsTimeout);
public bool Join(TimeSpan timeout);
public void Join( );
public void Resume( );
public void Start( );
public void Suspend( );
// Protected Instance Methods
protected override void Finalize( );
// overrides object
}