Daily Archives: December 3, 2013

Thread Pools (basics)

When you deal with many threads you should consider thread pools. Creating threads costs some time and resources. And even worse, you cannot reuse a thread.

Thread pool threads stay alive. The purpose is to use them again. They are waiting in a queue to be assigned new jobs. You do not have to instantiate a new thread each time you have a new job. Overall it reduces the number of threads. And in fact it does not help you a lot to have 100 threads running on a four processor machine. The system might even slow down, because it performs a lot of context switching.

Thread pools can automatically manage the amount of threads.

static void hello(object o) {
  for (int i = 0; i < 1000; i++) {
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " line " + i + " " + o as string);
    Thread.Sleep(2);    // let's wait 2 milliseconds to get some interaction between the two threads
  }
} //

static void Main(string[] args) {
  ThreadPool.QueueUserWorkItem(hello, "SomeFunnyParameter");
  ThreadPool.QueueUserWorkItem(hello);
  Console.ReadLine();
} //

 

Exiting Threads

You can use the Thread.Abort() method to kill a thread. This throws a ThreadAbort-Exception. The problem with this is that you do not know where exactly your program stops executing. It could be in the middle of an important calculation that makes a proper resource cleanup impossible. A more proper way would include a shared variable. By testing that variable you can exit your thread at predefined code positions.

private class parameters {
  //public double a;
  //public string s;
  public bool exitFlag = false;
}//

static private void myThread(object xParameters) {
  parameters p = xParameters as parameters;
  int i = 0;
  while (!p.exitFlag) {
    Console.WriteLine("thread loop number " + i++);
    Thread.Sleep(1000);
  }
  Console.WriteLine("good bye!");
  Thread.Sleep(2000);
} //

static void Main(string[] args) {
  Thread t = new Thread(new ParameterizedThreadStart(myThread));
  t.IsBackground = true;
  t.Name = "MyBackgroundThread";
  t.Priority = ThreadPriority.Normal;
  parameters p = new parameters();
  t.Start(p);

  Console.WriteLine("press return to exit the program");
  Console.ReadLine();

  p.exitFlag = true;
  t.Join();
} //

You can use a global static boolean to shut down a thread, but I think you will appreciate my solution using parameters as you can then reuse standard parameter interfaces and make your code more generic. You surely don’t want to deal with global variables when you have 100 threads running.

Exiting your application

In Windows.Forms applications you can use Application.Exit().  This method  terminates all message loops and closes all windows. You can eg. execute your cleanup code in the Form.OnClose events.
This method does not terminate your threads. If you do not deal with all your Foreground threads properly, then these threads  keep running. Therefore you must take measures to kill your threads.

The Environment.Exit() method is not part of Windows.Forms. It kills the process. Unsaved changes in forms may get lost. Again, you have to clean up properly and free resources.