C#COM服务器应该在何处调用其资源?

时间:2015-03-06 12:58:27

标签: c# com com-interop

我有一个用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或在那里进行任何更改。

2 个答案:

答案 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