特定のメソッドを実行するスレッドを作成しました。しかし、スレッドがまだ機能している場合でも、スレッドを強制終了したい場合があります。これどうやってするの? Thread.Abort()を試しましたが、「スレッドが中止されました」というメッセージボックスが表示されます。私は何をすべきか?
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. */
}
_
実際には、最後の手段としてAbort()のみを呼び出す必要があります。代わりに、変数を使用してこのスレッドを同期できます。
volatile bool shutdown = false;
void RunThread()
{
while (!shutdown)
{
...
}
}
void StopThread()
{
shutdown = true;
}
これにより、スレッドが実行していたことをきれいに完了し、アプリを既知の良好な状態に保つことができます。
最も正確でスレッドセーフな方法は、WaitHandleを使用して、停止するはずのスレッドにシグナルを送ることです。私はほとんどManualResetEventを使用します。
あなたのスレッドでは、あなたは持つことができます:
_private void RunThread()
{
while(!this.flag.WaitOne(TimeSpan.FromMilliseconds(100)))
{
// ...
}
}
_
ここで、_this.flag
_はManualResetEventのインスタンスです。つまり、スレッドの外部からthis.flag.Set()
を呼び出してループを停止できます。
WaitOneメソッドは、フラグが設定されている場合にのみtrueを返します。それ以外の場合は、指定されたタイムアウト(この例では100 ms)の後にタイムアウトし、スレッドはループをもう一度実行します。
スレッドを強制終了することはお勧めできません。停止して正常に終了させる必要があることを通知することをお勧めします。これにはさまざまな方法があります。
Thread.Interrupt
ブロックされている場合にそれを突く。WaitHandle
クラスを使用してシグナルを送信します。この答え ですでに行っているため、各メソッドの使用方法を再ハッシュする必要はありません。
スレッドが中止されたときにスレッドが何をしていたかを判断できないため、スレッドを中止することは非常に悪い考えです。
代わりに、スレッドがチェックできるプロパティを持ち、外部コードが設定できるようにします。スレッドが終了する安全な場所にあるときに、このブールプロパティをチェックします。
ジョンBに同意する
volatile bool shutdown = false;
void RunThread()
{
try
{
while (!shutdown)
{
/* Do work. */
}
}
catch (ThreadAbortException exception)
{
/* Clean up. */
}
}
void StopThread()
{
shutdown = true;
}
WebServerクラスにスレッドを強制終了する例もあります...
https://net7ntcip.codeplex.com/SourceControl/changeset/view/89621#1752948
Abortは問題が何であるかを理解しているだけで大丈夫だと思います...長時間実行中のタスクAbortは機能するが、(ShouldStopまたはActionBranchなど)などのフラグが必要になる前に状態を示している限り
例を確認してください!