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

时间:2009-09-03 08:26:52

标签: c# .net multithreading appdomain

这是对我initial question的跟进,我想提出我的发现,并要求更正,想法和见解。我的发现(或者更确切地说是解释)来自人们对我之前的问题的回答,阅读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卸载时引发,例如当使用单元测试框架运行类时(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. 终结
  4. WPF应用程序:未处理的异常

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

      1. System.AppDomain.CurrentDomain.DomainUnload
      2. 终结
      3. 在TestDriven.NET中运行的MbUnit:测试失败(未处理的异常由MbUnit处理)

        1. AppDomain.CurrentDomain.DomainUnload
        2. 终结
        3. 问题:

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

5 个答案:

答案 0 :(得分:7)

由ssg31415926的问题/答案提示(这个问题有点颠倒),还有Application.SessionEnding在用户注销或关闭时调用。它在Exit事件之前调用。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

  1. 终结器执行的默认超时为2秒。

答案 3 :(得分:1)

你写道:

  

System.AppDomain.CurrentDomain.UnhandledException :(如果在默认的AppDomain中处理:)为任何线程中的任何未处理的异常引发,无论线程启动的是什么AppDomain。这意味着,这可以用作catch-all for所有未处理的例外。

我不认为这是正确的。请尝试以下代码:

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处理程序,并且线程将以静默方式崩溃(或者如果在调试器中运行它,则唠叨你)。

答案 4 :(得分: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.
}