web-dev-qa-db-ja.com

アプリケーションの終了を検出する方法は?

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

イベント:

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

  • _System.AppDomain.CurrentDomain.DomainUnload_:デフォルトのAppDomain以外のAppDomainがアンロードされると発生します。ユニットテストフレームワーク(TestDriven.NETを備えたMbUnit)でクラスを実行する場合。

  • _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サイトなど
61
user65199

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

7
Ray

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

2
FooBarTheLittle

あなたが書く:

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ハンドラーは呼び出されず、スレッドは静かにクラッシュします(または、デバッガーで実行した場合は問題が発生します)。

1
Eyvind
  1. ファイナライザの実行のデフォルトのタイムアウトは2秒です。
1
unknown

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

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.
}
0
Daj Shung