62

这是我最初问题的后续,我想介绍我的发现并要求更正、想法和见解。我的发现(或者更确切地说是解释)来自人们对我之前的问题的回答,即阅读 MSDN .NET 3.5 文档和调试 .NET 3.5 代码。我希望这对像我一样想知道如何检测应用程序何时终止的人来说是有价值的。

事件:

  • System.AppDomain.CurrentDomain.ProcessExit: 在进程退出时引发,例如在默认值AppDomain和其他所有内容被卸载后[总执行时间仅限于 3 秒!]。对于 WPF,请System.Windows.Application.Exit改用。对于 Windows 窗体,Application.Run(...)在 main 方法之后运行代码。

  • System.AppDomain.CurrentDomain.DomainUnload:在AppDomain非默认AppDomain卸载时引发,例如在使用单元测试框架(MbUnit 和 TestDriven.NET)运行类时。

  • 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. 终结者

MbUnit 在 TestDriven.NET 中运行:测试失败(未处理的异常由 MbUnit 处理)

  1. AppDomain.CurrentDomain.DomainUnload
  2. 终结者

问题:

  • 我的解释/发现是否正确?
  • 你知道我遗漏的更多细节吗?例如,终结器的总执行时间是多少?
  • 你知道我知道的任何其他事件/想法吗?
  • 有哪些事件,它们在其他应用程序(例如 Windows 窗体、Web 服务、ASP.NET 网站等)中引发的顺序是什么?
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 回答