Home   Cover Cover Cover Cover
 

Threads

Example "Simple Thread"

The following example creates two threads t0 and t1 that print a series of characters to the console:

/book/samples/4/Threading/SimpleThread.cs
using System; 
using System.Threading;

public class ThreadExample {
  public static void RunT0() {
    for (int i = 0; i < 10; i++) { 
      Console.Write("x");
      Thread.Sleep(100);  
    }
  }
  public static void RunT1() {
    for (int i = 0; i < 10; i++) { 
      Console.Write("o");
      Thread.Sleep(100);  
    }
  }
  public static void Main() {
    Thread t0 = new Thread(new ThreadStart(RunT0));
    t0.Start();
    Thread t1 = new Thread(new ThreadStart(RunT1));
    t1.Start();
  }
}




Example "Stop a Thread with method Abort"

The following example shows how a thread can be interrupted with the method Abort:

/book/samples/4/Threading/AbortExample.cs
using System; 
using System.Threading;

public class ThreadAbort {
  public static void Go() {
    try { while (...) Console.Write("X"); } 
    catch (ThreadAbortException e) { Console.WriteLine(e.Message); }
  }
  public static void Main() {
    Thread t = new Thread(new ThreadStart(Go));
    t.Start();
    Thread.Sleep(5000); // Main thread is blocks for 5000ms, while thread t continues
    t.Abort();
    t.Join();
    Console.WriteLine("ready");
  }
}




Example "Abort a Thread through a condition"

In the following example this is achieved by setting running to false.

/book/samples/4/Threading/AbortAlternativeExample.cs
public class ThreadAbortAlternative {
  static bool running = true;
  public static void Go() {
    while (running) Console.Write ("X");
  }
  public static void StopThread() {
    running = false;
  }
  public static void Main() {
    Thread t = new Thread(new ThreadStart(Go));
    t.Start();
    StopThread();
  }
}




Example "Threadpools"

The following example shows how different sorts of tasks can be registered with a thread pool. Two sorts of task are registered: WorkerProcess is suitable for long-running tasks and TinyWorkerProcess for short tasks that are finished within 5000 ms. In addition, the Main method continuously monitors the number of currently available worker threads and displays this on the console:

/book/samples/4/Threading/ThreadPooling.cs
using System; 
using System.Threading;

public class ThreadPooling {
  public static void WorkerProcess(object state) {
    for (;;) { // infinite task
      Thread.Sleep(2000);  
      Console.WriteLine("WorkerProcess: {0}", state);
    }
  }
  public static void TinyWorkerProcess(object state) {
    Thread.Sleep(5000); // short task
    Console.WriteLine("TinyWorkerProcess: {0}", state);
  }
  public static void Main(string[] argv) {
    int workers;  // worker threads
    int asyncIOs;  // asynchronous I/O threads
    // How many worker and async. I/O threads are at most available for the various tasks?
    ThreadPool.GetMaxThreads(out workers,out asyncIOs);
    Console.WriteLine("max. worker threads: {0}", workers);
    Console.WriteLine("max. asynchronous I/O threads: {0}", asyncIOs);
    // register three tasks that run forever
    for(int i = 0; i < 3; i++) 
      ThreadPool.QueueUserWorkItem(new WaitCallback(WorkerProcess), i);
    // add three further tasks that take at most 5000 ms before they terminate
    for(int i = 0; i < 3; i++)
      ThreadPool.QueueUserWorkItem(new WaitCallback(TinyWorkerProcess), i);
    // permanently monitor the number of available worker threads
    for (;;) {
      Thread.Sleep(5000);
      ThreadPool.GetAvailableThreads(out workers, out asyncIOs);
      Console.WriteLine("currently available worker threads: {0}", workers);
    }
  }
}




Example "Lock"

A lock statement sets a lock on a specified object (usually the shared resource itself). While a thread executes a lock statement no other thread can carry out a lock statement on the same object. This guarantees mutual exclusion for a critical region that must not be simultaneously executed by several threads.

/book/samples/4/Threading/Lock.cs
using System; 
using System.Threading;

public class LockExample {
  public static void RunT0() {
    lock (Console.Out) {
      for (int i = 0; i < 10; i++) { Console.Write('x'); Thread.Sleep(100); }
    }
  }
  public static void RunT1() {
    lock (Console.Out) {
      for (int i = 0; i < 10; i++) { Console.Write('o'); Thread.Sleep(100); }
    }
  }
  public static void Main() {
    new Thread(new ThreadStart(RunT0)).Start();
    new Thread(new ThreadStart(RunT1)).Start();
  }
}




Example "Monitor"

The following example demonstrates the use of the class Monitor:
/book/samples/4/Threading/Monitor.cs
using System; 
using System.Collections; 
using System.Threading;

public class MonitorExample {
  Queue lpt; // line printer queue
  public void AddBlocking(object elem) {
    lock (lpt.SyncRoot) {
      lpt.Enqueue(elem);
    }
  }
  public bool AddNonBlocking(object elem) {
    if (! Monitor.TryEnter(lpt.SyncRoot)) return false;
    try { lpt.Enqueue(elem); }
    finally { Monitor.Exit(lpt.SyncRoot); }
    return true;
  }
}

Beispiel "Wait and Pulse"

The following example shows a classic buffer synchronization using Wait and Pulse. A buffer is used by several threads that can use buf.Put(ch) to introduce a character ch into the buffer and ch = buf.Get() to take a character out of the buffer. If the buffer is full or empty the executing thread must wait until another thread takes out or respectively puts in a character.
/book/samples/4/Threading/WaitPulse.cs
using System;
using System.Threading;

public class Buffer {
  const int size = 16;
  char[] buf = new char[size];
  int head = 0, tail = 0, n = 0;  // n ... fill level
  public void Put(char ch) {
    lock(this) {
      while (n >= size) Monitor.Wait(this);  // buffer full
      buf[tail] = ch; tail = (tail + 1) % size; n++;
      Monitor.Pulse(this);  // notify possibly waiting Get thread
    }
  }
  public char Get() {
    lock(this) {
      while (n <= 0) Monitor.Wait(this);  // buffer empty
      char ch = buf[head]; head = (head + 1) % size; n--;
      Monitor.Pulse(this);  // notify possibly waiting Put thread
      return ch;
    }
  }
}