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

发布于 2024-08-03 13:02:43 字数 1938 浏览 5 评论 0原文

这是我的初始问题的后续问题,我想展示我的发现并寻求更正、想法和见解。我的发现(或者更确切地说是解释)来自人们对我之前问题的回答、阅读 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:当默认 AppDomain 之外的 AppDomain 卸载时引发,例如使用单元测试框架运行类时(MbUnit 与 TestDriven.NET)。

  • System.AppDomain.CurrentDomain.UnhandledException:(如果在默认 AppDomain 中处理:)针对任何线程中的任何未处理的异常而引发,无论 AppDomain< /code> 线程开始于。这意味着,这可以用作所有未处理异常的捕获所有。

  • System.Windows.Application.Exit:WPF 应用程序(即默认AppDomain)正常退出时引发。重写System.Windows.Application.OnExit来利用它。

  • 终结器(C# 中的析构函数):当垃圾收集器释放非托管资源时运行。 [总执行时间有限!]。

事件顺序:

WPF 应用程序:正常退出

  1. System.Windows.Application.Exit
  2. System.AppDomain.CurrentDomain.ProcessExit
  3. Finalizers

WPF 应用程序:未处理的异常

  1. System.AppDomain.CurrentDomain.UnhandledException

MbUnit 在 TestDriven.NET 中运行:通过测试(正常退出)

  1. System.AppDomain.CurrentDomain.DomainUnload
  2. Finalizers

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

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

问题:

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

This is a follow up to my initial question and I would like to present my findings and ask for corrections, ideas and insights. My findings (or rather interpretations) come from people's answers to my previous question, reading MSDN .NET 3.5 documentation and debugging .NET 3.5 code. I hope this will be of value to someone who was wondering like me how to detect when an application terminates.

Events:

  • System.AppDomain.CurrentDomain.ProcessExit: raised when process exits, e.g. after the default AppDomain and everything else was unloaded [Total execution time is limited to just 3 seconds!]. For WPF, use System.Windows.Application.Exit instead. For Windows Forms, run code after Application.Run(...) in main method.

  • System.AppDomain.CurrentDomain.DomainUnload: raised when an AppDomain other than default AppDomain unloads, e.g. when running classes with unit testing frameworks (MbUnit with TestDriven.NET).

  • System.AppDomain.CurrentDomain.UnhandledException: (if handled in default AppDomain:) raised for any unhandled exception in any thread, no matter what AppDomain the thread started in. This means, this can be used as the catch-all for all unhandled exceptions.

  • System.Windows.Application.Exit: raised when WPF application (i.e. the default AppDomain) exits gracefully. Override System.Windows.Application.OnExit to take advantage of it.

  • Finalizers (destructors in C#): run when garbage collector frees unmanaged resources. [Total execution time is limited!].

Order of events:

WPF application: graceful exit

  1. System.Windows.Application.Exit
  2. System.AppDomain.CurrentDomain.ProcessExit
  3. Finalizers

WPF application: unhandled exception

  1. System.AppDomain.CurrentDomain.UnhandledException

MbUnit running inside TestDriven.NET: passed test (graceful exit)

  1. System.AppDomain.CurrentDomain.DomainUnload
  2. Finalizers

MbUnit running inside TestDriven.NET: failed test (unhandled exceptions are handled by MbUnit)

  1. AppDomain.CurrentDomain.DomainUnload
  2. Finalizers

Questions:

  • Are my interpretations/findings correct?
  • Do you know of more details that I have
    left out? E.g. what is the total
    execution time for finalizers?
  • Do you know of any other events /
    ideas that I be aware of?
  • What events are there and what order do they get raised in other applications, e.g. Windows Forms, Web Service, ASP.NET web site, etc?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

樱花细雨 2024-08-10 13:02:43

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

Prompted by ssg31415926's question/answer (this question is a bit reversed), there's also Application.SessionEnding which is called when the when the user logs off or shuts down. It is called before the Exit event.

当爱已成负担 2024-08-10 13:02:43

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

When Dispatcher.BeginInvokeShutdown() is called, Application.Exit will not be called.

清晨说晚安 2024-08-10 13:02:43
  1. 终结器执行的默认超时时间为 2 秒。
  1. The default timeout for a finalizer's execution is 2 seconds.
债姬 2024-08-10 13:02:43

你写:

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 处理程序,并且线程只会默默地崩溃(或者如果您在调试器中运行它,则会对您进行唠叨)。

You write:

System.AppDomain.CurrentDomain.UnhandledException: (if handled in default AppDomain:) raised for any unhandled exception in any thread, no matter what AppDomain the thread started in. This means, this can be used as the catch-all for all unhandled exceptions.

I do not think that this is correct. Try the following code:

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);
            }
        }
    }
}

As far as I can tell, the UnhandledException handler is never called, and the thread will just silently crash (or nag at you if you run it in the debugger).

何止钟意 2024-08-10 13:02:43

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

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

Just add a new event on your main form:

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.
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文