C# 如何检测应用程序何时终止?

C# 如何检测应用程序何时终止?,c#,.net,multithreading,appdomain,C#,.net,Multithreading,Appdomain,这是我的后续行动,我想提出我的发现,并要求更正、想法和见解。我的发现(或者更确切地说是解释)来自人们对我前面问题的回答,阅读MSDN.NET3.5文档和调试.NET3.5代码。我希望这对像我这样想知道如何检测应用程序何时终止的人来说是有价值的 事件: System.AppDomain.CurrentDomain.ProcessExit:当进程退出时引发,例如,在默认的AppDomain之后,并且卸载了所有其他内容[总执行时间仅限于3秒!]。对于WPF,请改用System.Windows.App

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

事件:

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

  • 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应用程序:优雅退出

  • System.Windows.Application.Exit
  • System.AppDomain.CurrentDomain.ProcessExit
  • 终结器
  • WPF应用程序:未处理的异常

  • System.AppDomain.CurrentDomain.UnhandledException
  • 在TestDriven.NET内运行的MbUnit:通过测试(优雅退出)

  • System.AppDomain.CurrentDomain.DomainUnload
  • 终结器
  • 在TestDriven.NET内部运行的MbUnit:测试失败(未处理的异常由MbUnit处理)

  • AppDomain.CurrentDomain.DomainUnload
  • 终结器
  • 问题:

    • 我的解释/发现是否正确
    • 你知道我有更多的细节吗 遗漏?总数是多少 终结器的执行时间
    • 你知道还有其他的活动吗/ 我知道的想法
    • 在其他应用程序(例如Windows窗体、Web服务、ASP.NET网站等)中有哪些事件以及它们的引发顺序

    由ssg31415926的问题/答案提示(此问题有点颠倒),还有一个在用户注销或关闭时调用的。它在退出事件之前被调用

  • 终结器执行的默认超时为2秒

  • 调用
    Dispatcher.BeginInvokeShutdown()
    时,将不会调用
    Application.Exit

    您编写:

    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处理程序,线程将自动崩溃(如果在调试器中运行它,则会对您唠叨)。

    只需在主窗体上添加一个新事件:

    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.
    }
    

    您对此有一个来源,不是吗?请注意/FYI:这仅在.NET 3.0+中可用,您需要链接到System.Core.dll才能在.NET 2.0中使用它。我发现这一行也不清楚。也许@user65199意味着如果事件“在默认AppDomain中处理”。显然,如果捕获到异常,则不会引发UnhandledException事件。该事件是否仅在默认AppDomain中引发,即使是在另一个AppDomain中实际启动的线程上的未处理异常(与您的示例从默认AppDomain启动相反)?我想这可能是他想要表达的意思,但我不记得这是否是规则。