1

私には理解できない問題があります。助けてください。TcpClient を使用して一部のハードウェアへのインターフェイスを処理するクラスを作成しました。このクラスが破壊される前に、最後のコマンドを HW に送信する必要があります。

これを解決するために、IDisposable.Dispose を実装して最後のコマンドの送信を処理し、接続を閉じました。また、デストラクタで Dispose を呼び出しました。これは、この記事で読んだ 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 を明示的に呼び出さずに最後のコマンドが常に送信されるようにする方法を教えてください。

4

1 に答える 1

4

明らかにまだ範囲外ではないオブジェクトが破棄されている理由を教えてください。

オブジェクト自体には「スコープ」という概念がありません。プログラムの最後に、クラスのTcpClient インスタンスの両方がファイナライズの対象になります。どちらが最初にファイナライズされるかは保証されません。TcpClientが最初にファイナライズされている(そして接続が閉じられている)ように聞こえるため、問題が発生します。

最善の解決策は、そもそもこれをファイナライズに依存しないことです。独自のファイナライザーを削除し (クライアントが を呼び出さない場合、ある時点で接続が閉じられることに注意してください) 、すべてDisposeを確実に破棄してくださいプログラムが正常に (つまり、制御するパスを介して) 終了したと仮定して、プログラムが終了するときの整然とした方法。

于 2015-01-20T16:46:51.380 に答える