.NETスレッド:起動されていないスレッドで中止をキャプチャするにはどうすればよいですか?
-
14-10-2019 - |
質問
編集:これは固着点のようですので、邪魔にならないようにしてください。
私はこれを同期に使用していません。単に長期にわたるタスクが必要 /望ましくなくなったときに単純に殺すためです。
仮説的に: :これらのスレッドが単にコンソール(たとえば "スレッド1")に書き込み、ランダムな長さをスリープしてから終了すると仮定します。彼らが中止されている場合、私は彼らに別のコンソールの書き込みで私に知らせてほしい(たとえば、「スレッド1が中止された」)。そして、私はジャンプできるようになりたいです 真っ直ぐ 通常の機能を実行するチャンスがなく、実行する前に中止しようとする場合、中止コードにコードを中止します。通常の機能中に中止された場合、もちろん両方を印刷します。
Visual Studio 2008を使用して.NET 2.0を実行しているASPサイトで順番に実行したいスレッドの塊があります(それがどれだけ重要なのかわかりませんが、そこにあります)。それは、彼らが彼らの仕事をどれだけ通過しているかに関係なく実行する必要があります。だから私はこのようなスレッドを作ります:
Thread t = new Thread(delegate() {
try {
/* do things */
System.Diagnostics.Debug.WriteLine("try");
}
catch (ThreadAbortException) {
/* cleanup */
System.Diagnostics.Debug.WriteLine("catch");
}
});
さて、私が途中でスレッドのセットを中止したい場合、クリーンアップは後でラインの後半で望ましい場合があります。 MSDNを介して見ると、.abort()が開始されていないスレッド()ができることを意味します。その後、.start()を使用して、その時点で例外を受け取り、正常に実行できます。または、.join()中止されたスレッドを()中止するのを待つことができます。おそらくそれらを組み合わせることができます。
http://msdn.microsoft.com/en-us/library/ty8d3wta(v=vs.80).aspx
スレッドが中止されるまで待つには、Abortメソッドを呼び出した後、スレッドの結合メソッドを呼び出すことができますが、待機が終了する保証はありません。
起動されていないスレッドで中断が呼び出された場合、スレッドはスタートが呼び出されると中止されます。ブロックされている、または睡眠中のスレッドで中断が呼び出された場合、スレッドは中断されてから中止されます。
さて、私がデバッグしてこのコードを踏むとき:
t.Abort(); // ThreadState == Unstarted | AbortRequested
t.Start(); // throws ThreadStartException: "Thread failed to start."
// so I comment it out, and
t.Join(); // throws ThreadStateException: "Thread has not been started."
決して出力を表示したり、TryまたはCatchブロックが到達したりするブレークポイントも表示されません。
奇妙なことに、ThreadStartExceptionは、ここから.Start()の可能性のあるスローとしてリストされていません。 http://msdn.microsoft.com/en-us/library/a9fyxz7d(v=vs.80).aspx (または他のバージョン)
スレッドがクリーンアップコードにジャンプするかどうかを示す開始パラメーターを使用することで、これを回避できると理解しています(おそらく私が行うことです)。そして私 たぶん......だろう .start()the thread、and .abort()it。しかし、不確定な時間は.STARTと.ABORTの間を通過する可能性があるため、私はそれが信頼できないと考えており、ドキュメントは私の元の方法が機能するはずだと言っているようです。
私は何かが足りませんか?ドキュメントは間違っていますか?
編集:OW。また、ノンパラメーター化されたスレッド(開始)で.Start(PARAM)を呼び出すことはできません。試行錯誤を除いて、スレッドがパラメーター化されているかどうかを調べる方法はありますか?私はプライベートM_DELEGATEを見ますが、公開されていません...
解決
使用するとき...
t.Abort();
t.Start();
... msdnが述べているように、threadStartExcpetionのinRexceptionにはthreadabortexeptionが含まれます。起動されていないスレッドで中断が呼び出された場合、スレッドはスタートが呼び出されると中止されます)
実行した場合...
t.Start();
t.Abort();
... threadabortexceptionは、スレッドが中止される前に開始する時間がなかったため、発生しない場合があります。
あなたが次のようなものをテストするなら...
t.Start();
Thread.Sleep(100);
t.Abort();
...「クリーンアップ」コードは常に実行する必要があります。
スレッドが何もしていなくても、クリーンアップコードを実行する必要がある場合、可能なソリューションは中止コールと一緒にクリーンアップ方法を開始するために可能になります。
さらに、スレッドの中止を避け、さまざまなテクニックを使用するようにしてください(http://msdn.microsoft.com/en-us/library/ms228964.aspx)
他のヒント
ドキュメントがあなたに暗示したことを理解していますが、それは何が起こるかではありません。スレッドを中止してから起動すると、決して実行されません。 CLRは、スレッドアボートが不安定なビジネスであることを知るのに十分賢く、したがってスレッドの実行を完全にスキップする機会は見逃せません。
おそらく、クリーンアップコードをサブルーチンにしてください。親スレッドが中止または中止について知っている場合、クリーンアップコードを明示的に呼び出します。
スレッドを中止した後に「クリーンアップ」という.NETの概念は、中止されたスレッドを実行していたアセンブリのアプリドメインをアンロードすることであることに留意してください。 「これがよくクリーンアップすることを期待しないでください」と言う別の方法です。最初に、スレッドを中止する必要のないデザインを常に探す必要があります。