是否有任何情况 TcpClient.Close 或 Socket.Close(0) 可能会阻止我的代码

本文关键字:Close 代码 我的 情况 任何 TcpClient 是否 Socket | 更新日期: 2023-09-27 18:21:44

由于没有指定 Close 方法是线程安全的,所以我应该从锁中调用它。我如何确定它不会阻塞我的线程?我应该禁用 LingerState 还是可以启用它?

顺便说一句,我需要同时调用TcpClient.Close和TcpClient.Client.Close吗?

是否有任何情况 TcpClient.Close 或 Socket.Close(0) 可能会阻止我的代码

根据 TcpClient.Close 的文档,调用此方法会释放实例。 快速浏览一下 ILSpy 就会发现它只是调用 Dispose ,这会调用Dispose(true)

此外,文档指出,调用Close也会释放基础Socket

事实上,在处理Socket之前,它调用了Shutdown(SocketShutdown.Both(。

鉴于 .NET 套接字是 Windows 套接字的包装器,则也会调用关闭函数,其文档指出:

注意:无论套接字上的SO_LINGER设置如何,关机功能都不会阻止。

但是,Socket重载其Close方法以接受超时参数,与TcpClient类似,Socket.Close方法调用Socket.Dispose(true),后者使用超时值来确定它是否可以阻塞。

根据 Socket.Close(int( 的文档:

如果需要在不先调用 Shutdown 的情况下调用 Close,则可以通过将 DontLinger 选项设置为 false 并指定非零超时间隔来确保发送排队等待传出传输的数据。然后,Close 将阻止,直到发送此数据或指定的超时到期。如果将 DontLinger 设置为 false 并指定零超时间隔,则 Close 将释放连接并自动丢弃传出排队的数据。

显然,TcpClientSocket都没有将超时值作为可设置属性向您公开,并且默认值不是0;因此,似乎为了避免阻塞,您必须在调用TcpClient.Close之前自己调用Socket.Close(0)

请记住,Close也可以抛出SocketException,尽管框架设计指南建议永远不要抛出对Dispose的调用。 也许这就是它被命名为 Close 并且TcpClient显式实现 Dispose 方法的原因之一。