是否存在 TcpClient.Close 或 Socket.Close(0) 会阻塞我的代码的情况? [英] Are there any cases when TcpClient.Close or Socket.Close(0) could block my code?
问题描述
由于没有指定 Close 方法是线程安全的,我应该从锁中调用它.我如何确定它不会阻塞我的线程?我应该禁用 LingerState 还是可以启用它?
As it's not specified that Close method is thread safe I should call it from the lock. How can I be sure that it will not block my thread? Should I disable LingerState or can it be enabled?
顺便说一句,我需要同时调用 TcpClient.Close 和 TcpClient.Client.Close 吗?
btw do I need to call both TcpClient.Close and TcpClient.Client.Close?
推荐答案
根据 TcpClient.Close 的文档,调用此方法处理实例.快速查看 ILSpy 会发现它只是调用了 Dispose
,后者调用了 Dispose(true)
.
According to the documentation for TcpClient.Close, calling this method disposes the instance. A quick look in ILSpy reveals that it simply calls Dispose
, which calls Dispose(true)
.
此外,文档指出调用 Close
也会处理底层的 Socket
.
Furthermore, the documentation states that calling Close
also disposes of the underlying Socket
.
实际上,在处理Socket
之前,它会调用Shutdown(SocketShutdown.Both).
In fact, before disposing of the Socket
, it calls Shutdown(SocketShutdown.Both).
鉴于 .NET 套接字是 Windows 套接字的包装器,关闭 函数也被调用,其文档说明:
Given that .NET sockets are wrappers for Windows sockets, the shutdown function is also called, and its documentation states:
注意无论套接字上的 SO_LINGER 设置如何,关闭功能都不会阻止.
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 值来确定它是否可能阻塞.
However, the Socket
overloads its Close
method to accept a timeout parameter and similar to TcpClient
, the Socket.Close
method calls Socket.Dispose(true)
, which uses the timeout value to determine whether or not it may block.
如果您需要在不先调用 Shutdown 的情况下调用 Close,则可以通过将 DontLinger 选项设置为 false 并指定非零超时间隔来确保发送排队等待传出传输的数据.然后关闭将阻塞,直到发送此数据或直到指定的超时到期.如果将 DontLinger 设置为 false 并指定零超时间隔,Close 将释放连接并自动丢弃传出的排队数据.
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)
.
Apparently, neither TcpClient
or Socket
expose the timeout value to you as a settable property and the default value is not 0
; therefore, it would seem that to avoid blocking you must call Socket.Close(0)
yourself prior to calling TcpClient.Close
.
请记住,Close
也可以抛出 SocketException
,尽管框架设计指南建议永远不要抛出对 Dispose
的调用.也许这就是为什么它被命名为 Close
并且 TcpClient
明确实现了 Dispose
方法的原因之一.
Keep in mind that Close
can also throw a SocketException
, despite the Framework Design Guideline's recommendation to never throw in a call to Dispose
. Perhaps that's one of the reasons why it's named Close
and TcpClient
explicitly implements the Dispose
method.
这篇关于是否存在 TcpClient.Close 或 Socket.Close(0) 会阻塞我的代码的情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!