text: .NET is a powerful tool, that can be used by applications that demand high scalability. Without using the Threading namespace, I doubt we can unleash the power of the .NET platform. Depending on the application you write, in most cases ThreadPool should be enough to perform small task asynchronously (in a separated thread). ThreadPool provides no access to the underlying threads, so we have no control over the thread and there’s no way to stop a thread once it has been started. If there’s a need to gain contol over the thread (suspending, aborting) then we have to use Thread instead. But for complex application even the Thread class may need a bit of extra features.
  My goal with this article is to:
  So let’s go...
  As I mentioned before the code described below was also used as basic for creating a class library, that allow an easy use of threading. If apply each part of this article plus if you ideas and a lot of work then the you can easily create a similar ThreadManager class as my own.
  In .NET it’s really easy to use Threading. First create a class for the Thread with a public Worker function.
  public class MyThread {
  public void Worker() {
  }
  }
  Let’s make a simple example: create a thread that will count down from an initial value to zero, then finish. The first thing 1 need to do is to pass the initial counter value to the class. I decided to use the constructor for this [using properties would be also fine, but then we would need also synchronization – and that will be presented later in this „lesson”].
  public class MyThread {
  private int _cnt;
  public MyThread(int initialCounterValue) {
  _cnt = initialCounterValue;
  }
  public void Worker() {
  <FONT color=green> // do the work
  </FONT>
  Now our thread class is finished. All we need to do is to make the thread work:
  public static void Test() {
  <FONT color=green> // create our thread class</FONT>
  MyThread mt = new MyThread(100);
  <FONT color=green> // create the threadstart and thread objects
  </FONT>
  If you call the Start() function from your code, the thread will be started. In a console application you would normally need a call to the Console.ReadLine() function to prevent the main thread (the application) from exitting [if the main application exits, then all it’s threads will be also aborted (if they are backgound threads)]. Here we do not need this call to the Console.ReadLine(). Why? Because we of the line t.Join(). This line makes the main thread (from which the t.Join() was called) to wait until the thread t finishes.
  We’ve created a working thread in the previous chapter. Now we need to generate an event when the thread finishes. We have to create a delegate first. This allows us to pass a function as a parameter. Delegates are type-safe, so the function we will pass as a delegate has to have the same signature as the delegate declaration. Add this line after the declaration of the member variable _cnt.
  public delegate void HandlerForFinish();
  Delegate declaration can also have arguments, but we have no need for this at the moment. If you need an example how to use arguments with delegates, please examine the ThreadHandler v1.0 source code.
  Now we have to declare the event. Put this line after the delegate declaration.
  public event HandlerForFinish OnFinish;
  And finally after the thread finishes, our event has to be invoked. This is done by adding the next line right after the // finish comment.
  if (OnFinish != null) OnFinish();
  As you see, it’s very simple. We first check, if an event is assigned and if sou, we simply invoke them (just like calling any other function in C#).
  Now we have to modify the Test() function a little bit, to see the event working. We’ve created a delegate function, then we assigned that function to the OnFinish event.
  So the „final” code is:
  public class MyThread {
  private int _cnt;
  public delegate void HandlerForFinish();
  public event HandlerForFinish OnFinish;
  public MyThread(int initialCounterValue) {
  _cnt = initialCounterValue;
  }
  public void Worker() {
  <FONT color=green> // do the work</FONT>
  while (_cnt > 0) {
  System.Console.WriteLine("Counter = " + _cnt.ToString());
  _cnt--;
  System.Threading.Thread.Sleep(500);
  }
  <FONT color=green> // finish</FONT>
  if (OnFinish ! = null) OnFinish();
  }
  }
  public void Test() {
  <FONT color=green> // create our thread class</FONT>
  MyThread mt = new MyThread(100);
  <FONT color=green> // assign a function to the event
  </FONT>
  In the previous chapter we got very close to the mentioned ThreadHandler class. Before moving to synchronization, we could re-arrange and modify our existing code a little bit and create a mini ThreadHandler.
  The ThreadHandler will have a:
  Also we will create an abstract class which will be used as a schema for the ThreadHandler. Also some public delegate methods will be needed...
  The previous example will be transformed to a new structure. The benefits of the new structure:
  NOTE: The next chapter will give a short description on synchronization.
  For each event we have to create delegates. These will be used also in the public abstract class.
  public delegate void HandlerForOnJob(ThreadHandlerEventArgs arg);
  The OnJob event is executed after the thread starts. It’ll invoke the worker function and do the calculation in a separated thread.
  public delegate void HandlerForOnAbort(ThreadHandlerEventArgs arg);
  This event is invoked only, when aborting was demanded.
  public delegate void HandlerForOnFinish(ThreadHandlerEventArgs arg);
  public delegate void HandlerForOnTerminate(ThreadHandlerEventArgs arg);
  This event should be raised always when the thread is aborted or it has finished processing. It is for supporting clean-up processes (releasing some resources, removing the ThreadHandler from a collection...
  public delegate void HandlerForOnException(ThreadHandlerExceptionArgs arg);
  This event is raised, when there is an error inside any of the event-delegates (except OnTerminate).
  As you se, we also need 2 special EventArg types:
  public class ThreadHandlerEventArgs : EventArgs {
  private ThreadHandler _threadHandler;
  public ThreadHandler Handler {
  get {
  return_threadHandler;
  }
  }
  public ThreadHandlerEventArgs(ThreadHandler threadHandler) {
  _threadHandler = threadHandler;
  }
  }
  <P>public class ThreadHandlerExceptionArgs : EventArgs {
  private ThreadHandler _threadHandler;
  private Exception _exception;
  public ThreadHandler Handler {
  get {
  return_threadHandler;
  }
  }
  public Exception Ex {
  get {
  return_exception;
  }
  }
  public ThreadHandlerExceptionArgs(ThreadHandler th, Exception ex) {
  _threadHandler = th;<
  BR > _exception = ex;
  }
  }</P>
  This class is not necessary. It only helps to make implementation easier.
  public abstract class IThreadClass {
  public IThreadClass() {
  }
  <FONT color=green>///
  /// Represents the method that will handle the OnJob event.
  ///
  </FONT>
  I will not include the full code from the project. Simply download the sources and check out the ThreadHandler.cs file. Also there is a simple test application (console app.) distributed along with the sources. There is a lot of comments in the ThreadHandler.cs file.
  Please read at least the coments in the Worker() functions.
  This exception needs a little bit of extra care... When a call is made to Abort to terminate a thread, the system throws.
  The .NET Framework has some classes for synchronisation. The most commonly used synchronisation „tool” is the mutual-exclusive lock (lock statement).
  NOTE: locking is only allowed on objects.
  Also it’s important avoid the use of the boxing conversion. (Boxing is the conversion of a value type to the type object. Boxing will create a new object from the value type. (For C++ coders: Boxing WILL NOT return the pointer to the original value. It will create a new object and return a reference to the newly created object).
  The most usefull function of the lock statement is in it’s simplicity. It has also an special „advantage”: if your code inside a lock-statement throws an error, the exclusive lock is released immediately after leaving the block of the lock-statement.
  How lock works: when an exclusive lock is acquired, all other exclusive lock requests (threads from where the lock is requested) are delayed (blocked), until the first exclusive lock is released...
  NOTE: You can change the lock statement and use System.Threading.Monitor.Enter(...) and System.Threading.Monitor.Exit(...) for acquiring and releasing the exclusive lock.
  What is ThreadHandler? ThreadHandler is a class allowing you to use threading without additionally coding. To make you more happier, ThreadHandler comes with a ThreadManager class, which is actually an implementation of an advanced thread-pool for the ThreadHandler class.
  Any function which is implemented by using ThreadHandler gains the following abilities:
  Here is a list of the most control functions, properties of ThreadHandler.
  States: Invalid, Unstarted, Exception, Running, PausedImmediately, PausingRequested, Pausing, Paused, WaitForResuming, Resuming, Resumed, StoppingRequested, Stopping, Stopped, Aborting, Aborted, Finishing, Finished, Terminating, Terminated.
  Events: OnStart, OnJob, AfterSuspend, BeforeResume, OnAbort, OnException, OnFinish, OnTerminate
  Control functions/properties: State, Start, Stop, AbortStopping, DisableAbortStopping, Pause, Resume, PauseImmediately, Abort, AllowPausing, AllowStopping, WaitUntilPaused, WaitUntilTerminated.
  The „previous version” of this component is used in a working environment. It required a FSM (finite state machine) to achieve the same functionality.
  In the 2nd version I got rid of this constraint. Also added some extra functions to make the class more better. There are functions that will make the caller thread to wait until the ThreadHandler achieves Paused, PausedImmediately or Terminated state. Also the number of states were increased and synchronization bugs were fixed.
  THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR.