C# 单例IDisposable对象的正确处理

C# 单例IDisposable对象的正确处理,c#,.net,C#,.net,场景: 应用程序实例化实现IDisposable的类的单个实例。该实例通过一个静态成员公开,该成员使应用程序的所有部分都可以访问它。单个实例需要在应用程序的生命周期内保持活动状态 问题 在应用程序关闭和进程终止之前调用Dispose方法有多重要 我一直认为,在大多数这样的场景中,不必调用Dispose,因为流程的终止会自然地清理资源。我错了吗?这篇文章详细解释了为什么要处理事件发布 其他的是一个很好的实践 在某些情况下,gc不会收集Publisher,即使设置为null,它也会继续触发事件。如

场景:

应用程序实例化实现
IDisposable
的类的单个实例。该实例通过一个静态成员公开,该成员使应用程序的所有部分都可以访问它。单个实例需要在应用程序的生命周期内保持活动状态

问题

在应用程序关闭和进程终止之前调用
Dispose
方法有多重要


我一直认为,在大多数这样的场景中,不必调用
Dispose
,因为流程的终止会自然地清理资源。我错了吗?

这篇文章详细解释了为什么要处理事件发布 其他的是一个很好的实践

在某些情况下,gc不会收集Publisher,即使设置为null,它也会继续触发事件。

如果“应用程序关闭”意味着进程正在终止,那么从技术上讲,您不需要做任何事情。您的进程正在终止,操作系统将释放这些资源

我想象它们可能是一些模糊的情况,其中一些组件可以创建某种类型的文件或其他资源,并且如果未调用
Dispose
,则不一定会清除,即使进程终止

我想举个例子,尽管这是一个奇怪的角落案例。假设您在代码中引用并使用了一个组件。当您创建和使用此文件时,它会在您的计算机上创建一个2GB文件。现在让我们进一步说明,由于一个bug或糟糕的设计,这个组件在访问这个2GB文件的过程中,实际上关闭了文件句柄本身。现在,这个对象上的
Dispose
方法会清理这个文件,但它没有很好的文档记录。基本上,如果缺少对this的
Dispose
调用,将在计算机上留下一个文件。这绝对是一个角落的情况,不会导致您的机器“泄漏”任何东西,但您确实有一个2GB的文件就在那里


话虽如此,但最好的做法是在确定资源已用完时调用
Dispose
。你可以在你的单例上调用一个方法,比如说
Cleanup()
,它可以在你关机时运行。

如果你想确保你的Dispose方法被调用,并且如果它不是死亡或活着的情况,你可以附加到
AppDomain.CurrentDomain.ProcessExit


如果您必须确保资源已清理,请使用监视主可执行文件的shell可执行文件,然后进行清理。

我使用与Revit API完全相同的模式。现在,我正在取消订阅事件,并在应用程序关闭时关闭类。不确定是否需要。进程终止将删除所有内容。GC在这一点上并不重要。我将此标记为答案。我的结论是答案基本上是:“视情况而定”。我猜答案取决于该类型实现
IDisposable
的原因,以及它创建了哪些资源,以及如果不调用
Dispose
方法,哪些资源将无法清理。当进程退出时,操作系统会自动清除某些情况,如打开的文件流。其他情况可能涉及这样的情况:如果未调用
Dispose
方法,即使进程终止,也会留下垃圾。@usr清理文件句柄和文件是两件不同的事情。如果在创建文件时设置了关闭时的
FILE\u FLAG\u DELETE\u
标志,则操作系统也会清理文件。