我有一个用C#实现的COM对象(见下文)。它拥有一些IDisposable
资源。我应该在哪里处置该资源?
看起来永远不会调用终结器,我无法重载IUnknown::Release
方法。
[ComVisible(true)]
[Guid("1992EC2F-087A-4264-B5B2-5E2E757F1A75")]
public class ComServer
{
IDisposable disposableResource; //where to dispose IDisposable resource?
public ComServer()
{
disposableResource = File.Open(@"c:\somefile.txt", FileMode.OpenOrCreate);
Console.WriteLine("ComServer.ComServer");
}
~ComServer() //finalizer is never called!
{
disposableResource.Dispose();
Console.WriteLine("ComServer.~ComServer");
}
}
已编辑:COM服务器在本机第三方应用程序中使用,无法在客户端调用Dispose
或在那里进行任何更改。
答案 0 :(得分:0)
Finalizer
。去寻找原因。
至于Dispose
,只有你可以决定何时处置你的对象。它取决于对象的体系结构和生命周期。一般来说,当不再需要该对象时,您应该调用Dispose()
。
您可以做的最好的事情是在IDisposable
上实施ComServer
并调用不再需要您的对象的Dispose
,或者您可以将它们包装在using
中} constructions。
Tseng提供了IDisposable
模式的标准实现的示例,但考虑到一个好的程序不需要终结器。一般来说,让对象有意依赖最终确定机制是一种不好的做法。
如果您想测试终结器,而不是可以创建对象,请不要将其丢弃,请致电GC.Collect()
。此调用将强制执行垃圾回收,如果您的对象符合垃圾回收条件,则将调用终结器。但请记住,永远不要将GC.Collect()
用作生产代码的一部分。
答案 1 :(得分:0)
无法保证何时调用finalize。您的ComServer应该实现IDiposable接口本身并在其中释放它的一次性成员。
来自MSDN(如果您覆盖Object.Finalize
)
如果要定义使用非托管资源的基类 具有或可能具有应该的子类 处置后,你应该实现IDisposable.Dispose方法和 提供Dispose的第二个重载,如下所述 部分。
class BaseClass : IDisposable
{
// Flag: Has Dispose already been called?
bool disposed = false;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing) {
// Free any other managed objects here.
//
}
// Free any unmanaged objects here.
//
disposed = true;
}
~BaseClass()
{
Dispose(false);
}
}
如果您需要处理,请明确调用Dispose,或尽可能使用using
。
using(ComServer com = new ComServer()) {
// operate on the ComServer
} // Dispose will be called automatically when the leaving the using block