C# スレッド

  • ある副スレッドの実行が完了するまで、主スレッドの実行を待機させるとき、主スレッドを副スレッドに結合する、といいます。
  • 以下は、myThreads というスレッドのコレクションがすでに定義されているものとして、このコレクションを走査していき、コレクション内にあるスレッドを現行のスレッドに結合させています。
foreach (Thread t in myThreads) t.Join();
  • 以下のように、待機時間を0として渡すことで、スレッドスケジューラが現在のスレッドを引き続き操作しようとした場合でも、別のスレッドの操作に移るよう通知することができます。
Thread.Sleep(0);
  • スレッドを停止させるには、Thread.Interrupt メソッドを使用します。注意点として、対象となるスレッドが、Join メソッド や Sleep メソッドによって、ブロックされていない場合、停止することなく、スレッドが操作を完了するまで、停止しないことがあります。
  • スレッドを即時終了させるには、Thead.Abort メソッドを呼び出します。このメソッドを呼び出すと、実行中のスレッドでは例外 ThreadAbortException が発生します。
  • Interlocked クラスは、メソッド Increment と Decrement、Exchange などを持っており、単に数値を変化させるだけではなく、同期処理の制御のもと実行されます。
  • Monitor クラスを使用することで、以下のように精密にリソースを管理することができます。注意として、メソッド Pulse を呼び出さない限り、待機中のスレッドは再実行されません。
public class MyTest
{
  private int counter = 0;
  public static void Main()
  {
    Thread[] theads =
    {
      new Thread(new ThreadStart(Decrement)),
      new Thread(new ThreadStart(Increment))
    }
    foreach(Thread t in threads)
    {
      t.IsBackground = true;
      t.Start();
    }
    foreach(Thread t in threads) { t.Join(); } // すべてのスレッドを結合させる
  }

  void Decrement()
  {
    try
    {
      Monitor.Enter(this); // 同期処理を始めます
      while(5 > counter)
      {
        Console.WriteLine("Decremnter waiting");
        Monitor.Wait(this);
      }
      while(counter > 0)
      {
        int temp = counter;
        temp--;
        Thread.Sleep(1);
        counter = temp;
        Console.WriteLine("Decrementer counter={0}", counter);
      }
    }
    finally
    {
      Monitor.Exit(this); // モニターによる同期処理が終了することを明示
    }
  }
  void Increment()
  {
    try
    {
      while(counter < 10)
      {
        Monitor.Enter(this); // 同期処理を始めます
        int temp = counter;
        temp++;
        Thread.Sleep(1);
        counter = temp;
        Console.WriteLine("Incrementer counter={0}", counter);
        Monitor.Pulse(this); // パルスを呼び出し、待機中のスレッドを呼び出します。
        Monitor.Exit(this);
      }
    }
    finally
    {
      Monitor.Exit(this); // モニターによる同期処理が終了することを明示
    }
  }
}

出力は以下のようになります。

Decrementer waiting
Incrementer counter=1
Decrementer waiting
Incrementer counter=2
Decrementer waiting
Incrementer counter=3
Decrementer waiting
Incrementer counter=4
Decrementer waiting
Incrementer counter=5
Decrementer counter=4
Decrementer counter=3
Decrementer counter=2
Decrementer counter=1
Decrementer counter=0
Incrementer counter=1
Incrementer counter=2
... // 省略
Incrementer counter=10