Reputation: 3171
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?
btw do I need to call both TcpClient.Close and TcpClient.Client.Close?
Upvotes: 2
Views: 1401
Reputation: 2652
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)
.
Furthermore, the documentation states that calling Close
also disposes of the underlying Socket
.
In fact, before disposing of the Socket
, it calls Shutdown(SocketShutdown.Both).
Given that .NET sockets are wrappers for Windows sockets, the shutdown function is also called, and its documentation states:
Note The shutdown function does not block regardless of the SO_LINGER setting on the socket.
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.
According to the 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.
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
.
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.
Upvotes: 4