Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#正确使用安全带进行处理_C#_Sockets_Dispose_Finalizer - Fatal编程技术网

C#正确使用安全带进行处理

C#正确使用安全带进行处理,c#,sockets,dispose,finalizer,C#,Sockets,Dispose,Finalizer,我知道并希望正确处理我的套接字资源。 在他们推荐使用的文档中,但我不确定这是如何使用的。我发现Socket类本身包含一个,但我不知道如何使用它。我是否需要处理把手和插座,或者仅处理把手就足够了?我假设在这个类中,我只对套接字操作使用句柄,对吗 public class MySocket : IDisposable { private SafeSocketHandle _handle; private bool _disposed = false; public MySo

我知道并希望正确处理我的套接字资源。 在他们推荐使用的文档中,但我不确定这是如何使用的。我发现Socket类本身包含一个,但我不知道如何使用它。我是否需要处理把手和插座,或者仅处理把手就足够了?我假设在这个类中,我只对套接字操作使用句柄,对吗

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;
    }
}
也许有人也能解释为什么应该使用安全手柄? 我的意思是,这还不够吗

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;
    }
}

直接管理非托管资源时,应使用
安全句柄

对于
Socket
,有一个底层非托管资源,但它由
Socket
类处理。您无需参与其中--
Socket
本身是一个托管资源,而不是非托管资源<代码>套接字
有自己的终结器,如果您忘记处置底层非托管资源,它将(可能)释放该资源

因此,在这里,您不需要担心
安全句柄
。只需实现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;
    }
}
事实上,许多编码标准要求非托管资源必须包装在
安全句柄
中。如果您这样做,就不需要实现完整的Dispose模式

如果确实需要实现完整的dispose模式,那么还需要编写终结器。你问题中的代码没有做到这一点


事实上,dispose模式会让用户走上一条非常危险的道路——在
void dispose(bool disposing)
方法中编写正确的代码确实非常困难,而且存在许多用户没有意识到的陷阱。这就是为什么.NET 2.0中引入了
SafeHandle
——运行时对它有特殊的支持,可以避免这些陷阱——但是关于
IDisposable
的建议似乎从未更新过。

请注意,您已经错过了代码示例中的终结器——它们很重要。@canton7不是模式的漏洞避免直接使用终结器?在本例中,它们也没有实现终结器:
SafeHandle
的目的是避免用户在尝试释放非托管资源时自食其果。如果您使用的是
SafeHandle
,您确实不需要实现完整的dispose模式,请参阅我的答案。但是,如果要实现完整的dispose模式,则需要正确地执行。在您的代码中,
GC.SuppressFinalize(this)
什么都不做(因为您没有终结器),并且没有任何东西会使用
false
调用您的
void Dispose(bool disposing)
方法。现在我更清楚了。谢谢所以基本上我可以使用SafeHandle来避免实现终结器。但因为套接字负责非托管资源,所以我不需要安全句柄。因此,简单的处理就足够了。但是,您能帮我一个忙,非常简单地解释一下,在这种情况下,非托管资源是什么,以及套接字是如何处理它们的?这将有助于我将来决定是否需要一个SafeHandle,
SafeHandle
的作用不仅仅是让您避免编写终结器:它避免了释放非托管资源时的一些陷阱。例如,您知道您的类可以在它的一个方法执行时完成吗?这意味着您可以在本机函数使用句柄时关闭它,这是非常糟糕的<代码>套接字是一个特别复杂的例子--
文件流
要简单得多,看看
\u handle
是如何使用的。