是否存在 TcpClient.Close 或 Socket.Close(0) 会阻塞我的代码的情况? [英] Are there any cases when TcpClient.Close or Socket.Close(0) could block my code?

查看:29
本文介绍了是否存在 TcpClient.Close 或 Socket.Close(0) 会阻塞我的代码的情况?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于没有指定 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 参数,类似于 TcpClientSocket.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.

根据 Socket.Close(int) 文档:

如果您需要在不先调用 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.

显然,TcpClientSocket 都将 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆