为什么Destructor没有被调用

本文关键字:调用 Destructor 为什么 | 更新日期: 2023-09-27 18:29:01

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

问题

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

问题

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

守则

所以我们有了告密者~

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服务记录连接类是否因任何给定原因而被破坏。当客户端连接时,它可以完美地工作。Web服务记录从它调用的每个方法。如果我显式调用ClientLogout,它就会工作。

我知道我可以实现IDisposable;但是,该对象不打算在一个方法的生命周期内使用。事实上,它打算在整个项目期间使用,而这个对象的失败基本上导致了整个项目的失败。(虽然我认为主要是一种方法…)

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

我的研究

微软表示,你应该使用解构器来发布明确引用网络连接的非托管资源。这些让我很为难。

为什么Destructor没有被调用

我认为应该为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块时,客户端将被注销。

微软表示,你应该使用解构器来发布明确引用网络连接的非托管资源。这些让我很为难。

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

例如,如果为数据访问层构建一个类来包装SqlConnection类型,则不需要析构函数或终结器,因为核心SqlConnection类型已经有了一个。不过,应该实现IDisposable并编写代码以确保及时处理,因此SqlConnection上的终结器将尽快被调用。但是,如果您要构建一个与SqlServer、MySql、Oracle、Access等竞争的全新数据库引擎,并为该新数据库引擎实现ADO.Net提供程序,则需要为您的连接类型编写终结器,因为目前还不存在。

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