[C#正确使用带有SafeSocketHandle的Dispose

问题描述 投票:0回答:1

我知道dispose pattern,并希望正确处置我的Socket资源。他们在文档中建议使用SafeHandles,但是我不确定System.Net.Socket的工作原理。我发现Socket类本身包含一个SafeSocketHandle,但我不知道如何使用它。我是否需要布置手柄和插座,或者仅布置手柄就足够了吗?我假设在该类中,我仅使用套接字操作的句柄,对吧?

public class MySocket : IDisposable
{
    private SafeSocketHandle _handle;
    private bool _disposed = false;

    public MySocket(AddressFamily addressFamily)
    {
        Socket s = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
        _handle = s.SafeHandle;
    }

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

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing)
        {
            _handle.Dispose();
        }

        _disposed = true;
    }
}

[也许有人也能够解释为什么应该使用SafeHandles?我是说这还不够吗?:

public class MySocket : IDisposable
{
    private Socket _socket;
    private bool _disposed = false;

    public MySocket(AddressFamily addressFamily)
    {
        _socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
    }

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

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing)
        {
            _socket.Dispose();
        }

        _disposed = true;
    }
}
c# sockets dispose finalizer
1个回答
0
投票

[当您直接管理非托管资源时,应使用SafeHandle

使用Socket,存在底层的非托管资源,但这由Socket类处理。您无需参与其中-Socket本身是托管资源,而不是非托管资源。 Socket有自己的终结器,如果您忘记处理它,它将释放底层的非托管资源。

所以,这里您不必担心SafeHandles。只需实现IDisposable并调用_socket.Dispose()


您不需要需要在此处实现完整的Dispose模式,除非您可能拥有一个拥有自己非托管资源的派生类。编写就足够了:

public class MySocket : IDisposable
{
    private Socket _socket;
    private bool _disposed = false;

    public MySocket(AddressFamily addressFamily)
    {
        _socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
    }

    public void Dispose()
    {
        _socket.Dispose();
        _disposed = true;
    }
}

实际上,许多编码标准要求将非托管资源必须包装在SafeHandle中。如果执行此操作,则无需实现完整的Dispose模式。

如果您do需要实现完整的处置模式,则还需要编写一个终结器。您问题中的代码无法执行此操作。

实际上,处置模式鼓励用户走上一条相当危险的道路-用void Dispose(bool disposing)方法编写正确的代码确实非常困难,并且存在大多数用户不知道的陷阱。这就是.NET 2.0中引入SafeHandle的原因-运行时对此有特殊的支持,避免了这些陷阱-但有关IDisposable的建议似乎从未更新过。

© www.soinside.com 2019 - 2024. All rights reserved.