SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

.NET Frameworkにおけるマルチスレッドプログラミングの基本

.NETマルチスレッドプログラミング 4:スレッドの優先順位と強制終了

.NET Frameworkにおけるマルチスレッドプログラミングの基本


  • X ポスト
  • このエントリーをはてなブックマークに追加

本稿は、.NET Frameworkにおけるマルチスレッドプログラミングの解説です。四部作の「パート4」では、スレッドの優先順位を変更したり、スレッドを強制終了・一時停止したりする方法について学びます。

  • X ポスト
  • このエントリーをはてなブックマークに追加

目次

はじめに

 本稿は、.NET Frameworkにおけるマルチスレッドプログラミングについて、四部作で解説してきた記事の最終回(パート4)です。パート4では、スレッドの優先順位を変更したり、スレッドを強制終了・一時停止したりする方法について解説します。

対象読者

 この記事はパート1パート2パート3の続きですので、パート1からお読みください。

必要な環境

 サンプルはVisual Studio .NET 2003で作成し、.NET Framework 1.1で動作確認をしています。

スレッドの優先順位

 サンプル「priority_01」は、現在のスレッドの名前を1000回出力するメソッドを、2つのスレッドで実行するだけのものです。

「VB.NET/priority_01/Class1.vb」:変更前 (VB.NET)
Class Class1
    'エントリポイント
    Shared Sub Main()
        '1つ目のスレッドを作成し、開始する
        Dim t1 As New System.Threading.Thread( _
            New System.Threading.ThreadStart(AddressOf WriteName))
        t1.Name = "1"
        t1.Start()

        'ちょっと待機
        System.Threading.Thread.Sleep(10)

        '2つ目のスレッドを作成し、開始する
        Dim t2 As New System.Threading.Thread( _
            New System.Threading.ThreadStart(AddressOf WriteName))
        t2.Name = "2"
        t2.Start()

        Console.ReadLine()
    End Sub

    '別スレッドで呼び出すメソッド
    Private Shared Sub WriteName()
        Dim i As Integer
        For i = 0 To 999
            'スレッドの名前を出力する
            Console.Write(System.Threading.Thread.CurrentThread.Name)
        Next i
    End Sub
End Class
「C#/priority_01/Class1.cs」:変更前 (C#)
class Class1
{
    //エントリポイント
    static void Main()
    {
        //1つ目のスレッドを作成し、開始する
        System.Threading.Thread t1 =
            new System.Threading.Thread(
            new System.Threading.ThreadStart(WriteName));
        t1.Name = "1";
        t1.Start();

        //ちょっと待機
        System.Threading.Thread.Sleep(10);

        //2つ目のスレッドを作成し、開始する
        System.Threading.Thread t2 =
            new System.Threading.Thread(
            new System.Threading.ThreadStart(WriteName));
        t2.Name = "2";
        t2.Start();

        Console.ReadLine();
    }

    //別スレッドで呼び出すメソッド
    private static void WriteName()
    {
        for (int i = 0; i < 1000; i++)
        {
            //スレッドの名前を出力する
            Console.Write(
                System.Threading.Thread.CurrentThread.Name);
        }
    }
}

 このコードを実行すると、下図のように、通常は「1」と「2」が交互に出力されると思います。

サンプル「priority_01」の実行例
サンプル「priority_01」の実行例

 次に、このコードに一行追加してみましょう。

「VB.NET/priority_01/Class1.vb」:変更後 (VB.NET)
Class Class1
    'エントリポイント
    Shared Sub Main()
        '1つ目のスレッドを作成し、開始する
        Dim t1 As New System.Threading.Thread( _
            New System.Threading.ThreadStart(AddressOf WriteName))
        t1.Name = "1"
        t1.Start()

        'ちょっと待機
        System.Threading.Thread.Sleep(10)

        '2つ目のスレッドを作成し、開始する
        Dim t2 As New System.Threading.Thread( _
            New System.Threading.ThreadStart(AddressOf WriteName))
        t2.Name = "2"
        '↓この行を追加↓
        t2.Priority = System.Threading.ThreadPriority.Highest
        t2.Start()

        Console.ReadLine()
    End Sub

    '別スレッドで呼び出すメソッド
    Private Shared Sub WriteName()
        Dim i As Integer
        For i = 0 To 999
            'スレッドの名前を出力する
            Console.Write(System.Threading.Thread.CurrentThread.Name)
        Next i
    End Sub
End Class
「C#/priority_01/Class1.cs」:変更後 (C#)
class Class1
{
    //エントリポイント
    static void Main()
    {
        //1つ目のスレッドを作成し、開始する
        System.Threading.Thread t1 =
            new System.Threading.Thread(
            new System.Threading.ThreadStart(WriteName));
        t1.Name = "1";
        t1.Start();

        //ちょっと待機
        System.Threading.Thread.Sleep(10);

        //2つ目のスレッドを作成し、開始する
        System.Threading.Thread t2 =
            new System.Threading.Thread(
            new System.Threading.ThreadStart(WriteName));
        t2.Name = "2";
        //↓この行を追加↓
        t2.Priority = System.Threading.ThreadPriority.Highest;
        t2.Start();

        Console.ReadLine();
    }

    //別スレッドで呼び出すメソッド
    private static void WriteName()
    {
        for (int i = 0; i < 1000; i++)
        {
            //スレッドの名前を出力する
            Console.Write(
                System.Threading.Thread.CurrentThread.Name);
        }
    }
}

 このコードを実行すると、例えば下図のように、「1」が幾つか出力された後に「2」が連続して1000回出力され、その後残りの「1」が出力されます。

サンプル「priority_02」の実行例
サンプル「priority_02」の実行例

 このコードでは、Threadオブジェクトt2だけPriorityプロパティを変更しました。ThreadクラスのPriorityプロパティは、スレッドの優先順位を取得、設定するプロパティです。優先順位はThreadPriority列挙体で指定し、優勢順位が高い方から、Highest, AboveNormal, Normal, BelowNormal, Lowestの5段階があります。PriorityプロパティのデフォルトはNormalですので、t2に設定したHighestt1Normalよりも優先順位が高くなります。

 このようなスレッドの優先順位を利用することにより、例えば、長く時間のかかる処理の間、ユーザーからの入力を待っているような場合に、ユーザーからの入力待ちのためのスレッドの優先順位を高くして、その反応を良くするといったことができます。

 なお、このスレッドの優先順位というのは、OSによるスレッドのスケジューリングの優先順位のことです。よってその動作はOSによるということになりそうですが、一般的には優先順位の高いスレッドの処理に、プロセッサがより多くの時間を割く(より多くのプロセッサタイムスライスを割り当てる)ことになります。その結果、優先順位の低いスレッドはより高いスレッドがすべて終了する(あるいは待機状態になる)まで実行されないということにもなります。詳しくは「スレッドのスケジューリング」をご覧ください。

スレッドを強制終了する

 サンプル「abort_01」は、長い時間のかかるDoSomethingメソッドを別スレッドで実行しますが、[Enter]キーを押すことにより、強制終了することができます。

「VB.NET/abort_01/Class1.vb」 (VB.NET)
Class Class1
    'エントリポイント
    Public Shared Sub Main()
        'Threadオブジェクトを作成する
        Dim t As New System.Threading.Thread( _
            New System.Threading.ThreadStart(AddressOf DoSomething))
        'スレッドを開始する
        t.Start()

        Console.ReadLine()

        'スレッドを中断する
        t.Abort()

        'スレッドが終了するまで待機する
        t.Join()

        Console.WriteLine("メインスレッドが終了")
        Console.ReadLine()
    End Sub

    '別スレッドで実行するメソッド
    Private Shared Sub DoSomething()
        Try
            'ループする
            Dim i As Integer
            For i = 0 To 999999
                Console.Write(".")
            Next i
        Catch e As System.Threading.ThreadAbortException
            'Abortが呼び出されたとき
            Console.WriteLine("Abortが呼び出されました")
        End Try

        Console.WriteLine("DoSomethingが終了")
    End Sub
End Class
「C#/abort_01/Class1.cs」 (C#)
class Class1
{
    //エントリポイント
    public static void Main()
    {
        //Threadオブジェクトを作成する
        System.Threading.Thread t =
            new System.Threading.Thread(
            new System.Threading.ThreadStart(DoSomething));
        //スレッドを開始する
        t.Start();

        Console.ReadLine();

        //スレッドを中断する
        t.Abort();

        //スレッドが終了するまで待機する
        t.Join();

        Console.WriteLine("メインスレッドが終了");
        Console.ReadLine();
    }

    //別スレッドで実行するメソッド
    private static void DoSomething()
    {
        try
        {
            //ループする
            for (int i = 0; i < 1000000; i++)
                Console.Write(".");
        }
        catch (System.Threading.ThreadAbortException)
        {
            //Abortが呼び出されたとき
            Console.WriteLine("Abortが呼び出されました");
        }

        Console.WriteLine("DoSomethingが終了");
    }
}

 このアプリケーションを実行すると、「.」が次々と表示されます。この時[Enter]キーを押すと、しばらくしてから「Abortが呼び出されました」と表示され、その後「メインスレッドが終了」と表示されます。

 このようにAbortメソッドを呼び出すことにより、スレッドを中止することができます。ただしAbortメソッドを呼び出してもすぐにスレッドが中止するわけではありませんので、ここではスレッドが間違いなく終了するまでJoinメソッドで待機しています。また、Abortメソッドが呼び出されたスレッドでは、ThreadAbortExceptionがスローされます。

 Abortメソッドを呼び出すと、スレッドの処理がセーフポイントに達した時に中止されます。セーフポイントに関しては「Thread.Suspend、ガベージ コレクション、およびセーフ ポイント」をご覧ください。

 Abortメソッドが呼び出されたスレッドでスレッドの中止要求をキャンセルするには、Thread.ResetAbortメソッドを使用します。サンプル「abort_02」では、「abort_01」のDoSomethingメソッドのcatch内に、ResetAbortメソッドを呼び出すコードを追加しています。

「VB.NET/abort_02/Class1.vb」 (VB.NET)
Class Class1
    'エントリポイント
    Public Shared Sub Main()
        'Threadオブジェクトを作成する
        Dim t As New System.Threading.Thread( _
            New System.Threading.ThreadStart(AddressOf DoSomething))
        'スレッドを開始する
        t.Start()

        Console.ReadLine()

        'スレッドを中断する
        t.Abort()

        'スレッドが終了するまで待機する
        t.Join()

        Console.WriteLine("メインスレッドが終了")
        Console.ReadLine()
    End Sub

    '別スレッドで実行するメソッド
    Private Shared Sub DoSomething()
        Try
            'ループする
            Dim i As Integer
            For i = 0 To 999999
                Console.Write(".")
            Next i
        Catch
            'Abortが呼び出されたとき
            Console.WriteLine("Abortが呼び出されました")
            'Abortをキャンセルする
            System.Threading.Thread.ResetAbort()
        End Try

        Console.WriteLine("DoSomethingが終了")
    End Sub
End Class
「C#/abort_02/Class1.cs」 (C#)
class Class1
{
    //エントリポイント
    public static void Main()
    {
        //Threadオブジェクトを作成する
        System.Threading.Thread t =
            new System.Threading.Thread(
            new System.Threading.ThreadStart(DoSomething));
        //スレッドを開始する
        t.Start();

        Console.ReadLine();

        //スレッドを中断する
        t.Abort();

        //スレッドが終了するまで待機する
        t.Join();

        Console.WriteLine("メインスレッドが終了");
        Console.ReadLine();
    }

    //別スレッドで実行するメソッド
    private static void DoSomething()
    {
        try
        {
            //ループする
            for (int i = 0; i < 1000000; i++)
                Console.Write(".");
        }
        catch (System.Threading.ThreadAbortException)
        {
            //Abortが呼び出されたとき
            Console.WriteLine("Abortが呼び出されました");
            //Abortをキャンセルする
            System.Threading.Thread.ResetAbort();
        }

        Console.WriteLine("DoSomethingが終了");
    }
}

 このアプリケーションでは、DoSomethingメソッド実行中に[Enter]キーを押すと、「Abortが呼び出されました」と表示された後、「DoSomethingが終了」と表示され、最後に「メインスレッドが終了」と表示されます。つまり、ResetAbortメソッドを呼び出さなかったときと比べ、「Console.WriteLine("DoSomethingが終了")」が実行されるようになります。

 MSDNライブラリにもあるように、このAbortメソッドは使用すべきではありません。Abortはどこで中断するか予測が付かないため、finallyブロックの実行中や、静的コンストラクタでスレッドが中断される恐れがあります。

 ユーザーがキャンセルボタンをクリックした場合に、このAbortを使用して処理を中断したくなるかもしれませんが、このような場合でもAbortを使わずに、volatile修飾子を利用したサンプル「volatile_03」で示したような方法で中断するようにしてください。

スレッドを一時停止する

 別のスレッドを一時停止して再開する方法として、SuspendメソッドとResumeメソッドが用意されています。サンプル「suspend_01」では、その使用例を示しています。

「VB.NET/suspend_01/Class1.vb」 (VB.NET)
Class Class1
    'エントリポイント
    Public Shared Sub Main()
        'WriteNumbersメソッドを別スレッドで実行する
        'Threadオブジェクトを作成する
        Dim t As New System.Threading.Thread( _
            New System.Threading.ThreadStart(AddressOf WriteNumbers))
        'スレッドを開始する
        t.Start()

        'しばらく待機する
        System.Threading.Thread.Sleep(100)

        Console.WriteLine()
        Console.WriteLine("Suspendメソッドを呼び出す")

        'スレッドを中断する
        t.Suspend()

        '再びしばらく待機する
        System.Threading.Thread.Sleep(5000)

        '中断したスレッドを再開する
        t.Resume()

        Console.WriteLine()
        Console.WriteLine("Resumeメソッドを呼び出す")

        'みたびしばらく待機する
        System.Threading.Thread.Sleep(100)

        Console.WriteLine()
        Console.WriteLine("Abortメソッドを呼び出す")

        'スレッドを終了する
        t.Abort()

        Console.ReadLine()
    End Sub

    '別スレッドで実行するメソッド
    Private Shared Sub WriteNumbers()
        '無限ループ
        While True
            Dim i As Integer
            For i = 0 To 9
                Console.Write(i)
            Next i
        End While
    End Sub
End Class
「C#/suspend_01/Class1.cs」 (C#)
class Class1
{
    //エントリポイント
    public static void Main()
    {
        //WriteNumbersメソッドを別スレッドで実行する
        //Threadオブジェクトを作成する
        System.Threading.Thread t = 
            new System.Threading.Thread(
            new System.Threading.ThreadStart(WriteNumbers));
        //スレッドを開始する
        t.Start();

        //しばらく待機する
        System.Threading.Thread.Sleep(100);

        Console.WriteLine();
        Console.WriteLine("Suspendメソッドを呼び出す");

        //スレッドを中断する
        t.Suspend();

        //再びしばらく待機する
        System.Threading.Thread.Sleep(5000);

        //中断したスレッドを再開する
        t.Resume();

        Console.WriteLine();
        Console.WriteLine("Resumeメソッドを呼び出す");

        //みたびしばらく待機する
        System.Threading.Thread.Sleep(100);

        Console.WriteLine();
        Console.WriteLine("Abortメソッドを呼び出す");

        //スレッドを終了する
        t.Abort();

        Console.ReadLine();
    }

    //別スレッドで実行するメソッド
    private static void WriteNumbers()
    {
        //無限ループ
        for (;;)
            for (int i = 0; i < 10; i++)
                Console.Write(i);
    }
}

 このプログラムを実行すると、次のようになります。

  1. 数字を幾つか表示
  2. 「Suspendメソッドを呼び出す」と表示
  3. 数字を幾つか表示
  4. 「Resumeメソッドを呼び出す」と表示
  5. 数字を幾つか表示
  6. 5秒間停止
  7. 数字を幾つか表示
  8. 「Abortメソッドを呼び出す」と表示

 ThreadクラスのSuspendメソッドでスレッドが一時停止し、Resumeメソッドで再開します。Suspendメソッドは、Abortメソッドと同様、呼び出してすぐにスレッドが一時停止するわけではなく、セーフポイントまで停止しません。

 基本的にSuspendメソッドは使用すべきではありません。スレッドを同期させたいならばlockなどを使うべきですし、別のスレッドを優先的に処理されるためにあるスレッドを一時停止させたいということであれば、ThreadPriorityプロパティでスレッドの優先順位を指定すべきです。

スレッドの状態

 現在のスレッドの状態は、Thread.ThreadStateプロパティで分かります。ThreadStateプロパティが取りうる値とその意味については「ThreadState」列挙体などを参照してもらうこととし、ここでは具体的なサンプルを示します。サンプル「state_01」を実行させれば、どのような時にThreadStateプロパティがどのような値となるかが分かります。

「VB.NET/state_01/Class1.vb」 (VB.NET)
Class Class1
    'エントリポイント
    Public Shared Sub Main()
        'Threadオブジェクトを作成する
        Dim t As New System.Threading.Thread( _
            New System.Threading.ThreadStart(AddressOf DoSomething))

        'スレッドの状態を表示
        Console.WriteLine("ThreadState:{0}", t.ThreadState.ToString())

        'スレッドを開始する
        Console.WriteLine("Startを呼び出す")
        t.Start()

        Console.WriteLine("ThreadState:{0}", t.ThreadState.ToString())
        System.Threading.Thread.Sleep(1000)
        Console.WriteLine("ThreadState:{0}", t.ThreadState.ToString())

        'ロックしてスレッドをブロックする
        Console.WriteLine("ロックしてスレッドをブロックする")
        System.Threading.Monitor.Enter(GetType(Class1))
        Console.WriteLine("ThreadState:{0}", t.ThreadState.ToString())
        System.Threading.Thread.Sleep(1000)
        Console.WriteLine("ThreadState:{0}", t.ThreadState.ToString())
        System.Threading.Monitor.Exit(GetType(Class1))

        'スレッドを中断
        Console.WriteLine("Suspendを呼び出す")
        t.Suspend()

        Console.WriteLine("ThreadState:{0}", t.ThreadState.ToString())
        System.Threading.Thread.Sleep(1000)
        Console.WriteLine("ThreadState:{0}", t.ThreadState.ToString())

        'スレッドの再開
        Console.WriteLine("Resumeを呼び出す")
        t.Resume()

        Console.WriteLine("ThreadState:{0}", t.ThreadState.ToString())
        System.Threading.Thread.Sleep(1000)
        Console.WriteLine("ThreadState:{0}", t.ThreadState.ToString())

        'スレッドの停止
        Console.WriteLine("Abortを呼び出す")
        t.Abort()

        Console.WriteLine("ThreadState:{0}", t.ThreadState.ToString())

        'スレッドが終了するまで待つ
        Console.WriteLine("Joinを呼び出す")
        t.Join()

        Console.WriteLine("ThreadState:{0}", t.ThreadState.ToString())

        Console.ReadLine()
    End Sub

    '別スレッドで実行するメソッド
    Private Shared Sub DoSomething()
        '無限ループ
        While True
            System.Threading.Monitor.Enter(GetType(Class1))
            System.Threading.Monitor.Exit(GetType(Class1))
        End While
    End Sub
End Class
「C#/state_01/Class1.cs」 (C#)
class Class1
{
    //エントリポイント
    public static void Main()
    {
        //Threadオブジェクトを作成する
        System.Threading.Thread t = 
            new System.Threading.Thread(
            new System.Threading.ThreadStart(DoSomething));

        //スレッドの状態を表示
        Console.WriteLine
            ("ThreadState:{0}", t.ThreadState.ToString());

        //スレッドを開始する
        Console.WriteLine("Startを呼び出す");
        t.Start();

        Console.WriteLine
            ("ThreadState:{0}", t.ThreadState.ToString());
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine
            ("ThreadState:{0}", t.ThreadState.ToString());

        //ロックしてスレッドをブロックする
        Console.WriteLine("ロックしてスレッドをブロックする");
        System.Threading.Monitor.Enter(typeof(Class1));
        Console.WriteLine
            ("ThreadState:{0}", t.ThreadState.ToString());
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine
            ("ThreadState:{0}", t.ThreadState.ToString());
        System.Threading.Monitor.Exit(typeof(Class1));

        //スレッドを中断
        Console.WriteLine("Suspendを呼び出す");
        t.Suspend();

        Console.WriteLine
            ("ThreadState:{0}", t.ThreadState.ToString());
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine
            ("ThreadState:{0}", t.ThreadState.ToString());

        //スレッドの再開
        Console.WriteLine("Resumeを呼び出す");
        t.Resume();

        Console.WriteLine
            ("ThreadState:{0}", t.ThreadState.ToString());
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine
            ("ThreadState:{0}", t.ThreadState.ToString());

        //スレッドの停止
        Console.WriteLine("Abortを呼び出す");
        t.Abort();

        Console.WriteLine
            ("ThreadState:{0}", t.ThreadState.ToString());

        //スレッドが終了するまで待つ
        Console.WriteLine("Joinを呼び出す");
        t.Join();

        Console.WriteLine
            ("ThreadState:{0}", t.ThreadState.ToString());

        Console.ReadLine();
    }

    //別スレッドで実行するメソッド
    private static void DoSomething()
    {
        //無限ループ
        for (;;)
        {
            System.Threading.Monitor.Enter(typeof(Class1));
            System.Threading.Monitor.Exit(typeof(Class1));
        }
    }
}

 このプログラムを実行すると、例えば次のように出力されます。

ThreadState:Unstarted
Startを呼び出す
ThreadState:Unstarted
ThreadState:Running
ロックしてスレッドをブロックする
ThreadState:Running
ThreadState:WaitSleepJoin
Suspendを呼び出す
ThreadState:SuspendRequested
ThreadState:Suspended
Resumeを呼び出す
ThreadState:Running
ThreadState:Running
Abortを呼び出す
ThreadState:AbortRequested
Joinを呼び出す
ThreadState:Stopped

 ThreadStateプロパティでスレッドの状態を調べるには、ビットマスクを使用します。例えば、スレッドが実行中か調べるには、次のようにします。

if ((t.ThreadState &
    (System.Threading.ThreadState.Unstarted |
    System.Threading.ThreadState.Stopped)) == 0)
{
    Console.WriteLine("スレッドは実行中です");
}

 また、スレッドが実行中かどうか調べるだけであれば、IsAliveプロパティを使うこともできます。スレッドの状態がUnstartedStoppedであればIsAlivefalseとなります。

待機中のスレッドを中断する

 Thread.Interruptメソッドは、待機中のスレッドを中断させます。サンプル「interrupt_01」では、Interruptメソッドを使用した例を示します。

「VB.NET/interrupt_01/Class1.vb」 (VB.NET)
Class Class1
    'エントリポイント
    Public Shared Sub Main()
        'Threadオブジェクトを作成する
        Dim t As New System.Threading.Thread( _
            New System.Threading.ThreadStart(AddressOf DoSomething))
        'スレッドを開始する
        t.Start()

        Console.WriteLine("Enterキーを押してください")
        Console.ReadLine()

        '待機状態を中断する
        Console.WriteLine("Interruptを呼び出す")
        t.Interrupt()

        Console.ReadLine()
    End Sub

    '別スレッドで実行するメソッド
    Private Shared Sub DoSomething()
        Try
            'ずっと待機状態にする
            System.Threading.Thread.Sleep _
                (System.Threading.Timeout.Infinite)
        Catch e As System.Threading.ThreadInterruptedException
            Console.WriteLine("ThreadInterruptedExceptionがスロー")
        End Try

        Console.WriteLine("別スレッドが終了")
    End Sub
End Class
「C#/interrupt_01/Class1.cs」 (C#)
class Class1
{
    //エントリポイント
    public static void Main()
    {
        //Threadオブジェクトを作成する
        System.Threading.Thread t = 
            new System.Threading.Thread(
            new System.Threading.ThreadStart(DoSomething));
        //スレッドを開始する
        t.Start();

        Console.WriteLine("Enterキーを押してください");
        Console.ReadLine();

        //待機状態を中断する
        Console.WriteLine("Interruptを呼び出す");
        t.Interrupt();

        Console.ReadLine();
    }

    //別スレッドで実行するメソッド
    private static void DoSomething()
    {
        try
        {
            //ずっと待機状態にする
            System.Threading.Thread.Sleep
                (System.Threading.Timeout.Infinite);
        }
        catch (System.Threading.ThreadInterruptedException)
        {
            Console.WriteLine("ThreadInterruptedExceptionがスロー");
        }

        Console.WriteLine("別スレッドが終了");
    }
}

 DoSomethingメソッドを実行する別スレッドは、Thread.Sleepにより無限にブロックされます。しかし、ブロックされているスレッドのInterruptメソッドを呼び出すことによって、スレッドを中断します。この時、例外ThreadInterruptedExceptionがスローされます。

 Interruptメソッドで中断するスレッドは、ThreadStateプロパティがWaitSleepJoinの状態のスレッドです。スレッドがWaitSleepJoinとなるのは、Thread.Sleepメソッドを呼び出したときの他に、Thread.Joinメソッドや、Monitor.EnterWaitメソッドでブロックされているときなどです。なお、WaitSleepJoinとなっていないスレッドでInterruptを呼び出した場合は、次にWaitSleepJoinとなったときに中断されます。

 このInterruptメソッドも基本的には使用すべきではありません。

次のページ
スレッドローカルストレージ

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
.NET Frameworkにおけるマルチスレッドプログラミングの基本連載記事一覧

もっと読む

この記事の著者

どぼん!(ドボン!)

DOBON.NET内で.NET Frameworkの機能を紹介したWebサイト.NET Tipsやメールマガジン「.NETプログラミング研究」の発行人。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/141 2006/07/11 14:37

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング