ユーザーがAbort
を呼び出したが、プログラムが終了しているために、現在実行中のスレッドが途中で中止されているかどうかを示すイベントはありますか?プログラムが終了しているためにスレッドが中止されているかどうかを知る方法はありますか?
私はすべてのスレッドがスレッドIDに関する情報とともにシャットダウンするたびに、これを必要とします。
私はそれがAppDomainUnload
イベントになることを期待していましたが、the documentationはそれについてnilchと言います。
ランタイムは、プロセスがシャットダウンしているため、バックグラウンドスレッドを停止し、例外がスレッドでスローされません。ただし、AppDomain.Unloadメソッドがアプリケーションドメインをアンロードするためにスレッドが停止すると、ThreadAbortExceptionがフォアグラウンドスレッドとバックグラウンドスレッドの両方でスローされます。
実際にテストするには、長時間実行している2つのスレッド(最初はフォアグラウンドスレッド、もう1つはバックグラウンドスレッド)を作成し、すぐに現在のプロセスを終了してアンロードしようとする小さなプログラムを書きました現在のappdomain。
これは、DomainUnload
ハンドラを呼び出すだけでなく、実行中の2つのスレッドを中止しようと試みて、ThreadAbortException
を送信する必要があります。
しかし、それは起こりません。
出力ウィンドウには、次の出力が表示されます。ここでは
[#10] [Foreground]Starting to do stuff.
The thread 0x183c has exited with code 0 (0x0).
[#9] [Worker]Starting to do stuff.
[#10] [Foreground]Slept for 5 seconds. Now finishing up the doing of stuff.
The thread 0x2954 has exited with code 0 (0x0).
The program '[11224] KnowAboutDyingThread.vshost.exe' has exited with code 0 (0x0).
は私のコードです:
using System;
using System.Diagnostics;
using System.Threading;
namespace KnowAboutDyingThread
{
// Source: https://msdn.microsoft.com/en-us/library/h339syd0%28v=vs.110%29.aspx
// When the runtime stops a background thread because the process is shutting down,
// no exception is thrown in the thread. However, when threads are stopped because the
// AppDomain.Unload method unloads the application domain, a ThreadAbortException is
// thrown in both foreground and background threads.
// I am trying that out
// I asked a question here about it: http://stackoverflow.com/questions/37552668/is-there-a-way-to-know-if-a-thread-is-being-aborted-because-the-program-is-termi
// Permalink: http://stackoverflow.com/q/37552668/303685
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
ThreadPool.QueueUserWorkItem(Do);
var t = new Thread(Do);
t.Name = "Foreground";
t.Start();
Process.GetCurrentProcess().Close();
}
private static void CurrentDomain_DomainUnload(object sender, EventArgs e)
{
Debug.Print("Unloading current appdomain...");
}
static void Do(object state)
{
try
{
Debug.Print(string.Format($"[#{Thread.CurrentThread.ManagedThreadId}] [{Thread.CurrentThread.Name ?? "Worker"}]Starting to do stuff."));
Thread.Sleep(5000);
Debug.Print(string.Format($"[#{Thread.CurrentThread.ManagedThreadId}] [{Thread.CurrentThread.Name ?? "Worker"}]Slept for 5 seconds. Now finishing up the doing of stuff."));
}
catch(ThreadAbortException abort)
{
Debug.Print(string.Format($"[#{Thread.CurrentThread.ManagedThreadId}] [{Thread.CurrentThread.Name ?? "Worker"}]Do got ThreadAbortException: {abort.GetType().Name}: {abort.Message}"));
}
catch(Exception ex)
{
Debug.Print(string.Format($"[#{Thread.CurrentThread.ManagedThreadId}] [{Thread.CurrentThread.Name ?? "Worker"}]Do had an exception: {ex.GetType().Name}: {ex.Message}"));
}
}
}
}
[1]: https://msdn.microsoft.com/en-us/library/system.appdomain.domainunload%28v=vs.110%29.aspx
'Thread.Abort'を実行しないでください。あなたが使っているものが何であれ、あなたは間違ったアプローチを取っています。 'Thread.Abort'は悪です。あなたは "Thread.Abort'を呼び出さずに私のプログラムをどのように終了させるのですか?もう一度、['Thread.Abort'は悪です。](http://stackoverflow.com/questions/3632149/question-about-terminating-a-thread-cleanly-in-net) – spender
私は病気をよく知っています'Thread.Abort'と' Thread.Interrupt'を使っているのですが、私の質問はこれらのメソッドを使うことの副作用とはほとんど関係がありません。 –
あなたはあなたが望む動作を得るために 'Process.GetCurrentProcess()。Kill();'をする必要があると思います。 'Close()'を実行すると正常にシャットダウンしますが、forgroundスレッドの 'Do'はクローズメッセージを監視する方法がないため、プロセスを起動しません。そして、それでもなお、「DomainUnload」は強制終了されてもまだ起動しないかもしれませんが、少なくとも「終了しました....」セクションは表示されません。 –