Vlad
Vlad

Reputation: 3171

Are there any cases when TcpClient.Close or Socket.Close(0) could block my code?

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

Answers (1)

Dave Sexton
Dave Sexton

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

Related Questions