次の方法で共有


スレッドの一時停止と中断

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

スレッドをスリープ状態にすることもできます。 スレッドがブロックされたりスリープ状態になったりする場合は、 ThreadInterruptedException を使用して待機状態から抜け出すことができます。

Thread.Sleep メソッド

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

あるスレッドが別のスレッドで Thread.Sleep を呼び出すことはできません。 Thread.Sleep は、現在のスレッドを常にスリープ状態にする静的メソッドです。

Timeout.InfiniteThread.Sleepを呼び出すと、別のスレッドがスリープ中のスレッドでThread.Interruptメソッドを呼び出すまで、スレッドはスリープ状態になります。 次の例は、スリープしているスレッドを中断することを示しています。

using System;
using System.Threading;

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

    private static void SleepIndefinitely()
    {
        Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' about to sleep indefinitely.");
        try
        {
            Thread.Sleep(Timeout.Infinite);
        }
        catch (ThreadInterruptedException)
        {
            Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' awoken.");
        }
        finally
        {
            Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' executing finally block.");
        }
        Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' finishing normal execution.");
        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.
Imports System.Threading

Module Example
    Public Sub Main()
        ' Interrupt a sleeping thread.
        Dim sleepingThread = New Thread(AddressOf SleepIndefinitely)
        sleepingThread.Name = "Sleeping"
        sleepingThread.Start()
        Thread.Sleep(2000)
        sleepingThread.Interrupt()
        sleepingThread.Join()
    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)
        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.Join を呼び出して、中断されたスレッドの実行が完了するまで呼び出し元のスレッドをブロックします。

スレッドの中断

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

Thread.Interruptが呼び出されたときにターゲット スレッドがブロックされない場合、スレッドはブロックされるまで中断されません。 スレッドがブロックしない場合は、中断されることなく完了する可能性があります。

待機がマネージド待機の場合、 Thread.Interrupt はすぐにスレッドをウェイクアップします。 待機がアンマネージド待機 (たとえば、Win32 WaitForSingleObject 関数へのプラットフォーム呼び出し呼び出し) である場合、 Thread.Interrupt はマネージド コードに戻るか、マネージド コードを呼び出すまでスレッドを制御できません。 マネージド コードの動作は次のとおりです。

こちらも参照ください