62

これは私の最初の質問へのフォローアップであり、私の調査結果を提示し、修正、アイデア、および洞察を求めたいと思います。私の調査結果 (またはむしろ解釈) は、MSDN .NET 3.5 のドキュメントを読み、.NET 3.5 コードをデバッグして、以前の質問に対する人々の回答から得られました。これが、私のようにアプリケーションの終了を検出する方法を知りたがっている誰かにとって価値のあるものになることを願っています。

イベント:

  • System.AppDomain.CurrentDomain.ProcessExit: プロセスが終了したときに発生します。たとえば、デフォルトAppDomainと他のすべてがアンロードされた後です [合計実行時間はわずか 3 秒に制限されています!]。WPF の場合は、System.Windows.Application.Exit代わりに使用してください。Windows フォームの場合Application.Run(...)、メイン メソッドの後にコードを実行します。

  • System.AppDomain.CurrentDomain.DomainUnload:ユニット テスト フレームワーク (TestDriven.NET を使用した MbUnit) でクラスを実行する場合AppDomainなど、既定以外のアンロード時に発生します。AppDomain

  • System.AppDomain.CurrentDomain.UnhandledException: (デフォルトで処理される場合AppDomain:) スレッドが開始されたスレッドに関係なく、任意のスレッドで未処理の例外に対して発生しますAppDomain。つまり、これはすべての未処理の例外のキャッチオールとして使用できます。

  • System.Windows.Application.Exit: WPF アプリケーション (つまり、デフォルトAppDomain) が正常に終了したときに発生します。System.Windows.Application.OnExitそれを利用するにはオーバーライドします。

  • ファイナライザー (C# のデストラクタ): ガベージ コレクターがアンマネージ リソースを解放するときに実行されます。【総実行時間制限あり!

イベントの順序:

WPF アプリケーション: 正常な終了

  1. System.Windows.Application.Exit
  2. System.AppDomain.CurrentDomain.ProcessExit
  3. ファイナライザー

WPF アプリケーション: 未処理の例外

  1. System.AppDomain.CurrentDomain.UnhandledException

TestDriven.NET 内で実行されている MbUnit: テストに合格 (正常終了)

  1. System.AppDomain.CurrentDomain.DomainUnload
  2. ファイナライザー

TestDriven.NET 内で実行されている MbUnit: テストに失敗しました (未処理の例外は MbUnit によって処理されます)

  1. AppDomain.CurrentDomain.DomainUnload
  2. ファイナライザー

質問:

  • 私の解釈/調査結果は正しいですか?
  • 私が省略した詳細を知っていますか?たとえば、ファイナライザーの合計実行時間は?
  • 私が知っている他のイベント/アイデアを知っていますか?
  • Windows フォーム、Web サービス、ASP.NET Web サイトなどの他のアプリケーションでは、どのようなイベントが発生し、どのような順序で発生しますか?
4

5 に答える 5

7

ssg31415926 の質問/回答 (この質問は少し逆です) によってプロンプトが表示され、ユーザーがログオフまたはシャットダウンしたときに呼び出されるApplication.SessionEndingもあります。Exit イベントの前に呼び出されます。

于 2009-09-08T21:23:11.647 に答える
2

Dispatcher.BeginInvokeShutdown()呼び出されると、呼び出さApplication.Exitれません。

于 2011-01-31T16:57:23.417 に答える
1
  1. ファイナライザーの実行のデフォルトのタイムアウトは 2 秒です。
于 2009-09-08T21:26:41.953 に答える
1

あなたが書く:

System.AppDomain.CurrentDomain.UnhandledException: (デフォルトの AppDomain で処理された場合:) スレッドが開始された AppDomain に関係なく、任意のスレッドで未処理の例外に対して発生します。つまり、これはすべての未処理の例外のキャッチオールとして使用できます。 .

これが正しいとは思いません。次のコードを試してください。

using System;
using System.Threading;
using System.Threading.Tasks;

namespace AppDomainTestingUnhandledException
{
    class Program
    {
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException +=
                (sender, eventArgs) => Console.WriteLine("Something went wrong! " + args);

            var ad = AppDomain.CreateDomain("Test");

            var service =
                (RunInAnotherDomain)
                ad.CreateInstanceAndUnwrap(
                    typeof(RunInAnotherDomain).Assembly.FullName, typeof(RunInAnotherDomain).FullName);

            try
            {
                service.Start();
            }
            catch (Exception e)
            {
                Console.WriteLine("Crash: " + e.Message);
            }
            finally
            {
                AppDomain.Unload(ad);
            }
        }
    }

    class RunInAnotherDomain : MarshalByRefObject
    {
        public void Start()
        {
            Task.Run(
                () =>
                    {
                        Thread.Sleep(1000);
                        Console.WriteLine("Uh oh!");
                        throw new Exception("Oh no!");
                    });

            while (true)
            {
                Console.WriteLine("Still running!");
                Thread.Sleep(300);
            }
        }
    }
}

私が知る限り、UnhandledException ハンドラーは決して呼び出されず、スレッドは黙ってクラッシュします (または、デバッガーで実行した場合はしつこく言います)。

于 2013-01-22T12:31:56.480 に答える
0

メイン フォームに新しいイベントを追加するだけです。

private void frmMain_Load(object sender, EventArgs e)
{
  Application.ApplicationExit += new EventHandler(this.WhenItStopsDoThis);
}

private void WhenItStopsDoThis(object sender, EventArgs e)
{
  //Program ended. Do something here.
}
于 2016-01-22T15:26:40.157 に答える