TcpClient提前放置

时间:2015-01-20 16:43:47

标签: c# destructor tcpclient idisposable objectdisposedexception

我有一个问题,我似乎无法弄清楚,请帮忙。我创建了一个类来使用TcpClient处理某些HW的接口。我希望这个类在它被销毁之前向HW发送最后一个命令。

为了解决这个问题,我已经实现了IDisposable.Dispose来处理最后一个命令的发送,然后关闭连接。我也在析构函数中调用了Dispose。这是我在this article中阅读的Microsoft建议。我的代码如下:

class MyHWInterface : IDisposable
{
    ~MyHWInterface()
    {
        Dispose();
    }

    private bool disposed = false;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            CloseConnection();
            disposed = true;
        }
    }

    private System.Net.Sockets.TcpClient Port = new System.Net.Sockets.TcpClient();

    public bool OpenConnection()
    {
        ...
    }

    private bool SendCommand(string command)
    {
        var strm = Port.GetStream(); // This throws the exception Cannot access disposed object!
        var w = new System.IO.StreamWriter(strm, System.Text.Encoding.ASCII);
        var r = new System.IO.StreamReader(strm, System.Text.Encoding.ASCII);
        w.WriteLine(command);
        w.Flush();
        string l = r.ReadLine();
        return l == "OK";
    }

    internal void CloseConnection()
    {
        try
        {
            SendCommand("power down now");
        }
        catch
        {
        }
        finally
        {
            Port.Close();
        }
    }
}

我的问题是:当我的程序结束时,我的MyHWInterface对象因此超出了范围,然后被垃圾收集。调用析构函数尝试发送最后一个命令,该命令失败,因为我的TcpClient已经被处理掉了。

请告诉我为什么一个明显尚未超出范围的物品正在处理中。请帮助一个方法,确保我的最后一个命令总是在没有显式调用Dispose的情况下发送。

1 个答案:

答案 0 :(得分:4)

  

请告诉我为什么一个明显尚未超出范围的物品正在处理中。

对象没有"范围"的概念。因此。在您的计划结束时,TcpClient 您班级的实例都有资格进行最终确定 - 并且不保证最先确定哪一项。听起来好像TcpClient正在最终确定(并且连接已关闭),因此问题就出现了。

最好的解决方法是首先不要依赖于最终确定 - 删除你自己的终结器(如果客户端没有调用Dispose,则意识到连接将在某个时刻关闭)当程序终止时,确保你以有序的方式处理所有事情,假设它干净地终止(即通过你控制的某个路径)。