需要知道应用程序何时关闭

8
有没有办法监控使用dll的应用程序何时关闭?DLL和应用程序都是使用C#编写的,但都不是Windows窗体。
我可以检查主应用程序何时关闭,但我希望DLL能看到“嘿,程序正在关闭并释放我,我应该在死之前快速做这个事情”。
有什么方法可以做到吗?或者我是否必须让应用程序分发“在你死之前做这个”?

1
为什么你需要那个?托管 DLL 通过垃圾收集器自动释放其资源。如果您需要释放非托管资源,请使用终结器。 - Vladislav Rastrusny
@FractalizerR:不建议使用finalizers来释放资源,因为它是不确定的。相反,对象应该实现“IDisposable”。 - Dirk Vollmar
4个回答

9
也许 AppDomain.ProcessExit 事件适合您?请注意以下内容(来自文档):

与进程关闭时所有终结器的总执行时间一样,所有 ProcessExit 事件处理程序的总执行时间也是有限的。默认值为两秒钟。非托管宿主可以通过使用 ICLRPolicyManager::SetTimeout 方法和 OPR_ProcessExit 枚举值来更改此执行时间。


谢谢。我已经尝试实现它,但是我不认为事件被调用了。不确定是否有什么诀窍可以使其工作。我做了AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);就我所知,它不会进入CurrentDomain_ProcessExit。我的检查方式是我想要的代码,以及当它到达那里时只需让一个winform消息框显示自己。该框应该出现然后消失,或者出现然后阻止应用程序正常关闭。但两者都没有发生。 :( - Nick
@Nick:你能分享一下该实现的详细信息吗(例如更新问题)。我按照你描述的方式尝试了一下,结果与预期相符。 - Fredrik Mörk
它对我有效(TM),但在第二或第三次尝试后就停止工作了!我正在通过 Ctrl-C 检测和优雅退出来完成我的进程。 - gatopeich

1

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

如果您需要以确定的方式释放资源或清理其他内容,则应查看 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
@Nick:释放未托管资源,比如你的设备,正是使用 IDisposable() 场景的典型案例。 - Dirk Vollmar
但是如果人们不使用dispose或using,那么它就不会被调用对吗? - Nick
此外,在进程在离开相应的作用域之前终止时,using语句不会被执行。 - irvnriir

0

AppDomain.ProcessExit通常可以工作,但如果进程被任务管理器终止,则不能保证触发。因此,如果您的设备驱动程序需要释放大量资源等(即它们可能不会被释放,直到GC处理完为止),则可能不是理想的选择。

有关更多详细信息,请参见Rick Stahls博客


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接