特定のメソッドを実行するスレッドを作成しました。しかし、スレッドがまだ機能していても、スレッドを強制終了したい場合があります。これどうやってするの?Thread.Abort() を試しましたが、「スレッドが中止されました」というメッセージボックスが表示されます。私は何をすべきか?
8 に答える
電話しないでくださいThread.Abort()
!
Thread.Abort
危険です。代わりに、平和的にシャットダウンできるように、スレッドに協力する必要があります。keepGoing
スレッドは、たとえば、スレッドを停止するときに false に設定するブール値フラグを設定するなどして、それ自体を強制終了するように指示できるように設計する必要があります。スレッドには次のようなものがあります
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 ミリ秒) 後にタイムアウトになり、スレッドはもう一度ループを実行します。
スレッドを強制終了するのは得策ではありません。停止する必要があることを通知し、正常に終了させることをお勧めします。これにはさまざまな方法があります。
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
影響が何であるかを理解するだけでアボートは大丈夫だと思います...長時間実行されるタスクの前に状態を示している限り、アボートは機能しますが、(ShouldStop または ActionBranch など) などのフラグが必要です。
例をチェックしてください!