由于没有指定 Close 方法是线程安全的,我应该从锁中调用它。我如何确定它不会阻塞我的线程?我应该禁用 LingerState 还是可以启用它?
顺便说一句,我需要同时调用 TcpClient.Close 和 TcpClient.Client.Close 吗?
最佳答案
根据documentation for TcpClient.Close ,调用此方法会释放该实例。快速浏览一下 ILSpy 就会发现,它只是调用 Dispose
,而后者又调用 Dispose(true)
。
此外,文档指出调用 Close
还会释放底层 Socket
。
事实上,在处置 Socket
之前,它会调用 Shutdown(SocketShutdown.Both) .
鉴于 .NET 套接字是 Windows 套接字的包装器,shutdown函数也被调用,其文档说明:
Note The shutdown function does not block regardless of the SO_LINGER setting on the socket.
但是,Socket
会重载其 Close
方法来接受 timeout 参数,并且与 TcpClient
类似, Socket.Close
方法调用 Socket.Dispose(true)
,它使用 timeout 值来确定是否可以阻塞。
根据documentation for Socket.Close(int) :
If you need to call Close without first calling Shutdown, you can ensure that data queued for outgoing transmission will be sent by setting the DontLinger option to false and specifying a non-zero time-out interval. Close will then block until this data is sent or until the specified time-out expires. If you set DontLinger to false and specify a zero time-out interval, Close releases the connection and automatically discards outgoing queued data.
显然,TcpClient
或 Socket
都没有将 timeout 值作为可设置属性向您公开,并且默认值不是 0
;因此,为了避免阻塞,您必须在调用 TcpClient.Close
之前自行调用 Socket.Close(0)
。
请记住,Close
也可能引发 SocketException
,尽管框架设计指南建议永远不要引发对 Dispose
的调用。也许这就是它被命名为 Close
且 TcpClient
显式实现 Dispose
方法的原因之一。
关于c# - 是否存在 TcpClient.Close 或 Socket.Close(0) 可能阻止我的代码的情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25811286/