为什么没有调用析构函数?

时间:2013-08-23 20:57:10

标签: c# web-services garbage-collection

我有一个非常有趣的场景,我希望一个类通知另一个实体它已被销毁;然而,它也没有做我想做的事。

问题

由于某种原因,解构主义者没有做它应该做的事情。

问题

为什么不调用析构函数并确保它确实进行了必要的清理。

守则

所以我们这里有线人〜

class Connection 
{
   public const int Port = 50000;// Can be any range between 49152 and 65536

    //Teh Constructor
    public Boolean Connect()
    {
        //SetInformation
        Information.Id = 545;

        using (var WebServ = new ClientSDKSoapClient("ClientSDKSoap"))
        {
            ContinueConnection.WaitOne();
            WebServ.ClientLogin(Information);
        }
        return true;
    }

    ~Connection()
    {
        using (var WebServ = new ClientSDKSoapClient("ClientSDKSoap"))
        {
            WebServ.ClientLogout(Information);
        }
    }
}

其他信息

我希望Web服务能够记录Connection Class是否因任何特定原因而被销毁。 当客户端连接时,它完美地工作。 Web服务记录从中调用的每个方法。如果我明确地调用ClientLogout,它将起作用。

我知道我可以实现IDisposable;但是,此对象不适用于一种方法的生命周期。事实上,它打算用于整个程序的持续时间和这个对象的失败基本上导致整个项目的失败。 (虽然我认为主要是一种方法......)

我需要释放网络连接;但是,它不在这个程序中,它在另一个程序中,除非调用ClientLogout,否则它不会被释放。

我的研究

Microsoft says您应该使用解构器来释放非托管资源,从而明确引用网络连接。这些让我非常难过。

2 个答案:

答案 0 :(得分:3)

我认为你应该为你的Connection类实现一个Dispose模式,而不是依赖一个模糊的解构器隐喻。这将是“规范”的方式。

public class Connection : IDisposable  // <== Inherit from IDisposable interface
{
    public const int Port = 50000;// Can be any range between 49152 and 65536

    private SomeType webserv; // Use whatever real type is appropriate here.
    private Information information = new Information();  // or whatever

    // This is a real constructor.
    public Connection()
    {
        //SetInformation
        information.Id = 545;

        webServ = new ClientSDKSoapClient("ClientSDKSoap"))
        webserv.ContinueConnection.WaitOne();
        webServ.ClientLogin(information);
    }

    // Implement IDisposable interface
    public void Dispose()
    {
        webServ.ClientLogout(information);
    }
}

然后使用它

using (var connection = new Connection())
{
    // Use the connection here.
}

当您离开using区块时,客户端将被注销。

答案 1 :(得分:1)

  

Microsoft表示您应该使用解构器来释放非托管资源,明确引用网络连接。这些让我非常难过。

这里的文档具有误导性。它实际上只意味着您需要在对象继承链中的某个位置使用终结器,以确保适当地清理所有非托管资源。但是,对于整个继承树,在首次分配非托管资源的级别上,您只需要此终结器一次

例如,如果为数据访问层构建一个类以包装SqlConnection类型,则不需要析构函数或终结器,因为核心SqlConnection类型已经有一个类。但应该做的是实施 IDisposable 并编写代码以确保及时处理,因此SqlConnection上的终结器会更快被调用而不是以后。但是如果你要构建一个与Sql Server,MySql,Oracle,Access等竞争的全新数据库引擎,并为这个新的数据库引擎实现ADO.Net提供程序,那么需要为你编写一个终结器连接类型,因为还没有。

在这种情况下,ClientSDKSoap类型已经有一个析构函数;你不需要写另一个。