5

以下の行を有効//1にすると、「proc exit」が出力されずにプログラムがクラッシュしますが、行の場合は//2「proc exit」が出力されます。どちらの場合も「未処理」btwが出力されます。

なぜ違いがあり、一般的なルールは何ですか? 明らかに、タスク マネージャーなどを使用してアプリを強制終了すると、「proc exit」が出力されなくなりますが、それ以外に、出力されないケースは何ですか?

static void Main(string[] args)
{
    Thread.GetDomain().UnhandledException +=
        (sender, eventArgs) => Console.WriteLine("unhandled");
    AppDomain.CurrentDomain.ProcessExit +=
        (sender, eventArgs) => Console.WriteLine("proc exit");
    //1 new Thread(_ => { throw new Exception(); }).Start();
    //2 ThreadPool.QueueUserWorkItem(_ => { throw new Exception(); });
    Thread.Sleep(1000);
    return;
4

2 に答える 2

5

このブログ投稿をご覧ください: AppDomain.ProcessExit は呼び出されることが保証されていません。投稿から引用:

AppDomain.ProcessExit が呼び出される保証はありません。それは非常に回復力があり、信頼性の低い IL から発生する可能性のある一般的な問題 (例外、メモリ不足など) に対処しますが、処理中のイベントが回復できないことがあります (失礼なプロセスのシャットダウンなど)。 .

(...)

コールバックは、プロセス内から呼び出されます。プロセスが乱暴に終了した場合、コールバックは呼び出されません。無作法に終了する一般的な原因には、次のものがあります。

  1. TaskManager または kernel32!TerminateProcess を介して外部から強制終了されました。
  2. Stackoverflow ハンドラーがガード ページを超えて消費します。

ProcessExit イベントは、誰かに「あなたがもうすぐ死ぬので電話してください」と伝えるようなものです。死が十分に早く来ると、彼らはメッセージを伝えられないかもしれません.

実際、私はあなたのコードを試してみましたが、1行目または2行目のコメントを外しても「proc exit」を出力しません! (Visual Studio 2013 で、すべての .NET バージョンに対してコンパイルを試みました)。もちろん、例外がスローされず、プロセスが正常に終了した場合は、それを出力します。(編集:リリースモードでコードをコンパイルすると「proc exit」メッセージが表示されますが、デバッグモードでコンパイルすると表示されません)

補足として、コードの推奨リファクタリングを次に示します (完全にはテストされておらず、おそらく不完全ですが、アイデアは得られます)。

static void Main(string[] args)
{
    Thread.GetDomain().UnhandledException +=
        (sender, eventArgs) => Exiting((Exception)eventArgs.ExceptionObject);
    AppDomain.CurrentDomain.ProcessExit +=
        (sender, eventArgs) => Exiting(null);
    //1 new Thread(_ => { throw new Exception(); }).Start();
    //2 ThreadPool.QueueUserWorkItem(_ => { throw new Exception(); });
    Thread.Sleep(1000);
    return;
}

static void Exiting(Exception exception)
{
    //Put common cleanup code here (or at the end of the method)

    if(exception == null)
    {
        Console.WriteLine("normal proc exit");
    }
    else
    {
        Console.WriteLine("unhandled exception: " + exception.GetType().Name);
    }
}
于 2013-12-19T07:47:36.847 に答える