web-dev-qa-db-ja.com

.NETスレッドの強制終了

特定のメソッドを実行するスレッドを作成しました。しかし、スレッドがまだ機能している場合でも、スレッドを強制終了したい場合があります。これどうやってするの? Thread.Abort()を試しましたが、「スレッドが中止されました」というメッセージボックスが表示されます。私は何をすべきか?

19
Jorge Branco

Thread.Abort()!を呼び出さないでください

_Thread.Abort_は危険です。代わりに、スレッドと協力して、スレッドを平和的にシャットダウンできるようにする必要があります。たとえば、スレッドを停止させたいときにfalseに設定したブールkeepGoingフラグを設定することで、スレッドを強制終了するようにスレッドを設計する必要があります。スレッドは次のようなものになります

_while (keepGoing)
{
    /* Do work. */
}
_

スレッドがSleepまたはWaitでブロックする可能性がある場合は、 Thread.Interrupt() を呼び出して、これらの関数からスレッドを切り離すことができます。次に、ThreadInterruptedExceptionを処理するようにスレッドを準備する必要があります。

_try
{
    while (keepGoing)
    {
        /* Do work. */
    }
}
catch (ThreadInterruptedException exception)
{
    /* Clean up. */
}
_
48
John Kugelman

実際には、最後の手段としてAbort()のみを呼び出す必要があります。代わりに、変数を使用してこのスレッドを同期できます。

volatile bool shutdown = false;

void RunThread()
{
   while (!shutdown)
   {
      ...
   }
}

void StopThread()
{
   shutdown = true;
}

これにより、スレッドが実行していたことをきれいに完了し、アプリを既知の良好な状態に保つことができます。

26
Jon B

最も正確でスレッドセーフな方法は、WaitHandleを使用して、停止するはずのスレッドにシグナルを送ることです。私はほとんどManualResetEventを使用します。

あなたのスレッドでは、あなたは持つことができます:

_private void RunThread()
{
    while(!this.flag.WaitOne(TimeSpan.FromMilliseconds(100)))
    {
        // ...
    }
}
_

ここで、_this.flag_はManualResetEventのインスタンスです。つまり、スレッドの外部からthis.flag.Set()を呼び出してループを停止できます。

WaitOneメソッドは、フラグが設定されている場合にのみtrueを返します。それ以外の場合は、指定されたタイムアウト(この例では100 ms)の後にタイムアウトし、スレッドはループをもう一度実行します。

9
Mark Seemann

スレッドを強制終了することはお勧めできません。停止して正常に終了させる必要があることを通知することをお勧めします。これにはさまざまな方法があります。

  • 使用する Thread.Interruptブロックされている場合にそれを突く。
  • フラグ変数をポーリングします。
  • WaitHandleクラスを使用してシグナルを送信します。

この答え ですでに行っているため、各メソッドの使用方法を再ハッシュする必要はありません。

7
Brian Gideon

スレッドが中止されたときにスレッドが何をしていたかを判断できないため、スレッドを中止することは非常に悪い考えです。

代わりに、スレッドがチェックできるプロパティを持ち、外部コードが設定できるようにします。スレッドが終了する安全な場所にあるときに、このブールプロパティをチェックします。

2
John Saunders

ジョンBに同意する

volatile bool shutdown = false;

void RunThread()
{

try
{
    while (!shutdown)
    {
        /* Do work. */
    }
}
catch (ThreadAbortException exception)
{
    /* Clean up. */
}
}

void StopThread()
{
   shutdown = true;
}
2
XenKid

WebServerクラスにスレッドを強制終了する例もあります...

https://net7ntcip.codeplex.com/SourceControl/changeset/view/89621#1752948

Abortは問題が何であるかを理解しているだけで大​​丈夫だと思います...長時間実行中のタスクAbortは機能するが、(ShouldStopまたはActionBranchなど)などのフラグが必要になる前に状態を示している限り

例を確認してください!

1
Jay