C# 处理多个应用程序使用的库中非托管资源的优雅方法
我的应用程序中的库需要全局使用非托管资源 为此,图书馆提供了以下服务:C# 处理多个应用程序使用的库中非托管资源的优雅方法,c#,singleton,unmanaged,idisposable,C#,Singleton,Unmanaged,Idisposable,我的应用程序中的库需要全局使用非托管资源 为此,图书馆提供了以下服务: 有一个单例类继承自IDisposable。 非托管资源的获取发生在类的Instance()方法中。 资源总是通过MySingleton对象访问,因此这似乎是确保非托管资源在需要时可用的一种合乎逻辑的方式 public class MySingleton : IDisposable { private static MySingleton instance; public static MySingleton
IDisposable
。
Instance()
方法中。
MySingleton
对象访问,因此这似乎是确保非托管资源在需要时可用的一种合乎逻辑的方式
public class MySingleton : IDisposable
{
private static MySingleton instance;
public static MySingleton Instance
{
get
{
if (instance == null)
{
lock (typeof(MySingleton))
{
if (instance == null)
{
instance = new MySingleton();
// Acquire unmanaged resource here
}
}
}
return instance;
}
}
public void Dispose()
{
// Release unmanaged resource here
}
}
问题
- 具有上述单例的库正由多个应用程序使用
- 为了确保正确清理非托管资源,我需要在每个应用程序中调用
(通常在MySingleton.Instance.Dispose()
块中,以确保即使在finally
情况下也会发生这种情况)异常
- 如果创建了另一个应用程序(即入口点),而作者忘记调用
方法,则可能会导致未被妥善清理的非托管资源Dispose
MySingleton
类添加一个析构函数来执行此操作,但在应用程序退出时似乎没有命中其中的断点。我猜这是因为GC是不确定的,可能应用程序在静态对象的析构函数被销毁之前就结束了,但我不确定
有没有一种优雅的方法可以确保始终清理此资源,而不依赖客户端应用程序显式调用
Dispose
来确保这种情况发生?关于您的析构函数没有被命中,请看这里:
虽然调用了析构函数,但我认为在调试时您看不到这一点。
对于您的单例,很明显,它在程序退出之前不会被调用,因为它是静态的
关于确保调用Dispose,我认为最好的方法是继承IDisposable并记录Dispose的需要。如果有一种自动处理东西的方法,您不认为MS会对SqlConnection或任何其他一次性类这样做吗?顺便说一句,我认为确定何时在类本身中处理实例不是一个好的做法。这样,您就限制了类的使用,并且无法知道将使用您的类的其他组件想要做什么。使用单例实现IDisposable听起来是错误的。谁负责处理该物品 当两个线程或两个进程试图访问资源时,应该发生什么?失败者应该阻止还是抛出异常 我认为您最好采用RAII方法,在这种方法中,您有一个实现IDisposable的类,并且该类仅在资源使用时有效:
class MyResource : IDisposable {
public MyResource() {
// Acquire resource here
}
public void Dispose() {
// Free resource here, along with extra stuff to attempt
// to catch situations where its not disposed
}
}
然后:
您不能保证使用库的每个其他开发人员都会记得正确地处理该类,但是任何未能在using语句中使用该类的人都可以通过一根锋利的大棒进行教育。您对singleton的静态引用将使它保持活动状态,而不管其他人是否实际使用它。如果您希望检测到对您的单身汉的所有外部引用何时消失,而您自己却无法使其保持活动状态,则必须执行以下操作之一:
using( var r = new MyResource() ) {
// Do work here.
}