由于没有指定Close方法是线程安全的,我应该从锁中调用它。我怎么能确定它不会阻止我的线程?我应该禁用LingerState还是可以启用它?
btw我是否需要同时调用TcpClient.Close和TcpClient.Client.Close?
答案 0 :(得分:2)
根据documentation for TcpClient.Close,调用此方法会释放实例。快速查看ILSpy可以看出它只是调用Dispose
,调用Dispose(true)
。
此外,文档指出调用Close
也会处理基础Socket
。
事实上,在处置Socket
之前,它会调用Shutdown(SocketShutdown.Both)。
鉴于.NET套接字是Windows套接字的包装器,还调用shutdown函数,其文档说明:
注意无论套接字上的SO_LINGER设置如何,关闭功能都不会阻止。
但是,Socket
重载其Close
方法以接受超时参数,类似于TcpClient
,Socket.Close
方法调用{{ 1}},它使用 timeout 值来确定它是否可以阻止。
根据documentation for Socket.Close(int):
如果您需要在不先调用Shutdown的情况下调用Close,则可以通过将DontLinger选项设置为false并指定非零超时间隔来确保排队等待传出传输的数据。然后关闭将阻止,直到发送此数据或直到指定的超时到期为止。如果将DontLinger设置为false并指定零超时间隔,则Close会释放连接并自动丢弃传出的排队数据。
显然,Socket.Dispose(true)
或TcpClient
都不会将超时值作为可设置属性公开给您,默认值不是Socket
;因此,为了避免阻止,您必须在致电0
之前自己致电Socket.Close(0)
。
请注意,TcpClient.Close
也可以抛出Close
,尽管框架设计指南的建议是永远不会打电话给SocketException
。也许这就是为什么它被命名为Dispose
和Close
明确实现TcpClient
方法的原因之一。