スレッドの一時中断および中断

スレッドの活動を同期する最も一般的な方法は、スレッドのブロックと解放を行うか、コード領域またはオブジェクトをロックすることです。 ロックとブロックのしくみの詳細については、「同期プリミティブの概要」を参照してください。

また、スレッドそのものをスリープ状態にすることもできます。 スレッドがブロックされているかまたはスリープ状態の場合は、ThreadInterruptedException を使用して待機状態を解除できます。

Thread.Sleep メソッド

Thread.Sleep メソッドを呼び出すと、メソッドに渡した時間の間または数ミリ秒間、現在のスレッドがすぐにブロックされ、残りのタイム スライスは別のスレッドに生成されます。 時間が経過すると、スリープ状態のスレッドは実行を再開します。

もう一方のスレッドが他方のスレッドに対して Thread.Sleep を呼び出すことはできません。 Thread.Sleep は静的メソッドであり、常に現在のスレッドがスリープ状態になります。

Timeout.Infinite の値を指定して Thread.Sleep を呼び出すと、スリープ状態のスレッドで Thread.Interrupt メソッドを呼び出す別のスレッドによって中断されるか、Thread.Abort メソッドの呼び出しによって中止されるまで、スリープ状態になります。 次の例は、スリープ状態のスレッドを中断する両方の方法を示しています。

using System;
using System.Threading;

public class Example
{
   public static void Main()
   {
      // Interrupt a sleeping thread.
      var sleepingThread = new Thread(Example.SleepIndefinitely);
      sleepingThread.Name = "Sleeping";
      sleepingThread.Start();
      Thread.Sleep(2000);
      sleepingThread.Interrupt();

      Thread.Sleep(1000);

      sleepingThread = new Thread(Example.SleepIndefinitely);
      sleepingThread.Name = "Sleeping2";
      sleepingThread.Start();
      Thread.Sleep(2000);
      sleepingThread.Abort();
   }

   private static void SleepIndefinitely()
   {
      Console.WriteLine("Thread '{0}' about to sleep indefinitely.",
                        Thread.CurrentThread.Name);
      try {
         Thread.Sleep(Timeout.Infinite);
      }
      catch (ThreadInterruptedException) {
         Console.WriteLine("Thread '{0}' awoken.",
                           Thread.CurrentThread.Name);
      }
      catch (ThreadAbortException) {
         Console.WriteLine("Thread '{0}' aborted.",
                           Thread.CurrentThread.Name);
      }
      finally
      {
         Console.WriteLine("Thread '{0}' executing finally block.",
                           Thread.CurrentThread.Name);
      }
      Console.WriteLine("Thread '{0} finishing normal execution.",
                        Thread.CurrentThread.Name);
      Console.WriteLine();
   }
}
// The example displays the following output:
//       Thread 'Sleeping' about to sleep indefinitely.
//       Thread 'Sleeping' awoken.
//       Thread 'Sleeping' executing finally block.
//       Thread 'Sleeping finishing normal execution.
//
//       Thread 'Sleeping2' about to sleep indefinitely.
//       Thread 'Sleeping2' aborted.
//       Thread 'Sleeping2' executing finally block.
Imports System.Threading

Module Example
    Public Sub Main()
        ' Interrupt a sleeping thread. 
        Dim sleepingThread = New Thread(AddressOf Example.SleepIndefinitely)
        sleepingThread.Name = "Sleeping"
        sleepingThread.Start()
        Thread.Sleep(2000)
        sleepingThread.Interrupt()

        Thread.Sleep(1000)

        sleepingThread = New Thread(AddressOf Example.SleepIndefinitely)
        sleepingThread.Name = "Sleeping2"
        sleepingThread.Start()
        Thread.Sleep(2000)
        sleepingThread.Abort()
    End Sub

    Private Sub SleepIndefinitely()
        Console.WriteLine("Thread '{0}' about to sleep indefinitely.",
                          Thread.CurrentThread.Name)
        Try
            Thread.Sleep(Timeout.Infinite)
        Catch ex As ThreadInterruptedException
            Console.WriteLine("Thread '{0}' awoken.",
                              Thread.CurrentThread.Name)
        Catch ex As ThreadAbortException
            Console.WriteLine("Thread '{0}' aborted.",
                              Thread.CurrentThread.Name)
        Finally
            Console.WriteLine("Thread '{0}' executing finally block.",
                              Thread.CurrentThread.Name)
        End Try
        Console.WriteLine("Thread '{0} finishing normal execution.",
                          Thread.CurrentThread.Name)
        Console.WriteLine()
    End Sub
End Module
' The example displays the following output:
'       Thread 'Sleeping' about to sleep indefinitely.
'       Thread 'Sleeping' awoken.
'       Thread 'Sleeping' executing finally block.
'       Thread 'Sleeping finishing normal execution.
'       
'       Thread 'Sleeping2' about to sleep indefinitely.
'       Thread 'Sleeping2' aborted.
'       Thread 'Sleeping2' executing finally block.

スレッドの中断

待機中のスレッドを中断するには、ブロックされているスレッドに対して Thread.Interrupt メソッドを呼び出して ThreadInterruptedException をスローさせます。これにより、スレッドは中断され、ブロックしている呼び出しから抜け出します。 スレッドは、ThreadInterruptedException をキャッチし、操作を継続するために適切な処理を行う必要があります。 スレッドがこの例外を無視した場合は、ランタイムがこの例外をキャッチし、そのスレッドを停止します。

注意

Thread.Interrupt が呼び出されたときに対象となるスレッドがブロックされていない場合、スレッドはブロックされるまで中断されません。 スレッドがまったくブロックされない場合は、中断されることなく完了することがあります。

待機がマネージド待機である場合、Thread.InterruptThread.Abort はどちらもすぐにスレッドを起動します。 待機がアンマネージ待機の場合 (プラットフォームが Win32 WaitForSingleObject 関数を呼び出した場合など)、Thread.InterruptThread.Abort はどちらも、スレッドがマネージド コードに戻るか、またはマネージド コードを呼び出すまで、そのスレッドを制御できません。 マネージド コードの動作は次のとおりです。

関連項目