WaiteNeの呼び出しの途中にある場合、どのようにアプリケーションを閉じますか?
-
28-09-2019 - |
質問
「きれいに」アプリケーションを閉鎖する標準的な方法はありますか WaitHandle
オブジェクトは、 WaitOne
?
たとえば、このような方法で並んでいる背景スレッドがあるかもしれません。
while (_request.WaitOne())
{
try
{
_workItem.Invoke();
}
finally
{
OnWorkCompleted();
}
}
電話せずにこのスレッドを処分する明白な方法は見当たりません Thread.Abort
(私が理解していることから、それは落胆しています)。電話 Close
に _request
オブジェクト(an AutoResetEvent
)ただし、例外がスローされます。
現在、このループを実行しているスレッドには IsBackground
に設定されたプロパティ true
, 、そしてアプリケーション 表示されます 適切に閉じる。しかし、それ以来 WaitHandle
道具 IDisposable
, 、これがコーシャと見なされているのか、それともアプリが終了する前にそのオブジェクトが本当に処分されるべきかどうかはわかりません。
これは悪いデザインですか?そうでない場合、このシナリオは通常どのように対処されますか?
解決
追加を定義します WaitHandle
呼び出されました _terminate
ループを終了してから使用するリクエストが表示されます WaitHandle.WaitAny
それ以外の WaitHandle.WaitOne
.
var handles = { _request, _terminate };
while (WaitHandle.WaitAny(handles) == 0)
{
try
{
_workItem.Invoke();
}
finally
{
OnCompleteWork();
}
}
他のヒント
スレッドがブロックしている場合(ブロックしているものに関係なく)呼び出すことができます Thread.Interrupt()
これにより、例外が発生します ThreadInterruptedException
(私は、それは少し違うかもしれないと思います)あなたはスレッド自体でこの例外を処理し、neccesaryのクリーンアップを行うことができます。
スレッドがスローするだけであることは注目に値します ThreadInterruptedException
ブロックしている場合、ブロックしていない場合は、次にブロックしようとするまで投げられません。
これは、私がこのテーマで読んだものからスレッドを終わらせる「安全な」方法です。
また、注目に値する:オブジェクトがIdisposableとFinializer(それが管理されていないリソースを使用する場合になる場合)の両方を実装する場合、GCは通常、廃棄するファイナルライザーを呼び出します。通常、これは非決定的です。ただし、アプリケーションの出口で呼び出されることを保証できます。非常に特別な状況下でのみ、彼らはそうしませんでした。 (Aなどの例外を終了する.NET環境 StackOverflowException
投げられます)
をセットする IsBackground
プロパティへ true
...アプリが終了したら、スレッドを自動的に閉じる必要があります。
あるいは、呼び出してスレッドを中断することができます Thread.Interrupt
そして、を処理します ThreadInterruptedException
. 。別のアイデアは電話することです _request.Set()
whileループに揮発性フラグをチェックして、アプリケーションが閉じているかどうか、または継続する必要があるかどうかを判断します。
private volatile bool _running = true;
while(_request.WaitOne() && _running)
{
//...
}
// somewhere else in the app
_running = false;
_request.Set();
プロセスが終了した後、オペレーティングシステムはクリーンアップすると思います。スレッドはiSbackgroundとしてマークされているため、CLRはプロセスとすべてのスレッドを終了するため、これは問題ではありません。