【问题标题】:Need to know when application is closing需要知道应用程序何时关闭
【发布时间】:2010-06-10 06:43:40
【问题描述】:

有没有办法监控使用 dll 的应用程序何时关闭? DLL 和应用程序都是 C#,也不是 Windows 窗体。

我可以检查主应用程序何时关闭,但我希望 DLL 看到“嘿,程序正在关闭并释放我,我应该在死前尽快完成这项工作”。

有什么办法吗?还是我坚持让应用程序“在你死前做这件事”?

【问题讨论】:

  • 你为什么需要它?托管 DLL 由垃圾收集器自动释放其资源。如果您需要释放非托管资源,请使用 Finalization。
  • @FractalizerR:推荐使用终结器来释放资源,因为它是不确定的。相反,对象应该实现IDisposable

标签: c# dll resources


【解决方案1】:

也许AppDomain.ProcessExit 事件对您有用?请注意以下内容(来自文档):

所有的总执行时间 ProcessExit 事件处理程序是有限的, 就像总执行时间一样 所有终结者都在过程中受到限制 关闭。默认值为两秒。 非托管主机可以更改此设置 通过调用执行时间 ICLRPolicyManager::SetTimeout方法 使用 OPR_ProcessExit 枚举 价值。

【讨论】:

  • 谢谢。我试图实现它,但是我不认为该事件被调用过。不确定是否有使它起作用的技巧。我做了 AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);据我所知,它不会进入 CurrentDomain_ProcessExit。我的检查方法是我想要的代码,以及当它到达那里时让一个winform消息框显示出来。该框应该出现然后消失,或者出现然后将应用程序从正常关闭状态挂起。但两者都没有发生。 :(
  • @Nick:您能否分享该实现的细节(例如更新问题)。我按照您的描述尝试了它,它按预期工作。
  • 它对我有用(TM),然后在第二次或第三次尝试时它停止工作!?我正在通过 Ctrl-C 检测和优雅退出来完成我的过程。
【解决方案2】:

我们不知道您的代码的详细信息,但您的类库需要知道进程何时退出这一事实可能表明您的应用程序存在设计缺陷。

如果您需要以确定的方式释放资源或清理其他内容,您应该查看IDisposable 接口。如果您的库公开的类实现了此接口,调用者可以通过调用Dispose() 轻松声明它们不再需要 dll 功能。

以下文章可能是进一步阅读的良好起点:

例如,您的类库中可能有以下类:

using System;
using System.IO;

public class ResourceManager : IDisposable
{
    private Stream _resource;
    private bool _disposed;

    public void Dispose()
    {
        Dispose(true);

        // Use SupressFinalize in case a subclass
        // of this type implements a finalizer.
        GC.SuppressFinalize(this);
    }

    public void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                Console.WriteLine("Exiting Process. Cleaning up.");
                // free resources here
                if (_resource != null)
                    _resource.Dispose();
                Console.WriteLine("Object disposed.");
            }

            // Indicate that the instance has been disposed.
            _resource = null;
            _disposed = true;
        }
    }
}

在您的主模块中,您可以通过以下方式使用; using 语句将保证调用 Dispose() 方法:

using System;
using System.Windows.Forms;

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        using (ResourceManager manager = new ResourceManager())
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

【讨论】:

  • 它是一个设备驱动程序,因此需要释放设备,并在使用它的应用程序离开且不执行清理职责时尽可能将其设置回中性状态。因此我需要它在 DLL 中。当程序使用 dll 时,它可能不会调用一次性的,它可能会离开。它将由我自己在我的程序以及其他可能没有相同编码的程序中使用。
  • @Nick:释放像你的设备这样的非托管资源正是使用IDisposable()的场景。
  • 但是如果人们不使用dispose,或者using,那么它就不会被调用吧?
【解决方案3】:

AppDomain.ProcessExit 将“正常”工作,但如果进程被任务管理器终止,则不能保证触发。因此,如果您的设备驱动程序需要释放大量资源等(即它们可能在 GC 开始之前不会被释放),它可能并不理想。

更多详情请见Rick Stahls blog

【讨论】:

    【解决方案4】:

    如果是控制台应用程序,您需要按照this question中的接受答案进行操作。 并且最好使用IDisposable接口进行开发。

    【讨论】:

      猜你喜欢
      • 2021-05-19
      • 1970-01-01
      • 1970-01-01
      • 2023-02-06
      • 1970-01-01
      • 2013-10-01
      • 2013-05-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多