Should I always call TcpClient.EndConnect (even when connection fails?)
-
22-09-2019 - |
Question
C# has several useful classes for networking tasks such as TcpClient and WebClient. Both have BeginX methods (BeginConnect and BeginGetResponse respectively) that according to MSDN should always be followed by EndX. Both accepts a delegate that is called once the operation is complete.
However, say we fail to establish a connection, and thus calling those methods would throw an exception. Should I still call the respective EndX methods, or should I first check whether the connection was established, and only then call them?
Alternatively, in the following example, should I use OnSocketConnected1 or OnSocketConnected2?
static TcpClient m_client;
private static void OnSocketConnected1 (IAsyncResult asynchronousResult)
{
try
{
m_client.EndConnect(asynchronousResult);
}
catch { }
}
private static void OnSocketConnected2(IAsyncResult asynchronousResult)
{
if (m_client.Connected)
{
try
{
m_client.EndConnect(asynchronousResult);
}
catch { }
}
}
static void Main(string[] args)
{
m_client = new TcpClient();
m_client.BeginConnect("http://www.example.com", 555, OnSocketConnected, null);
Console.ReadLine();
}
Thanks
Solution
MSDN Quote, TcpClient.BeginConnect
The asynchronous BeginConnect operation must be completed by calling the EndConnect method. Typically, the method is invoked by the asyncCallback delegate.
I see no exception to that rule here. And your fields shouldn't matter (read: Version 1, call EndConnect unconditionally, right away).
OTHER TIPS
My instinct would say yes, as it would probably allow the framework to garbage-collect the IAsyncResult object.
private static void OnSocketConnected1 (IAsyncResult asynchronousResult)
{
try
{
m_client.EndConnect(asynchronousResult);
}
catch { }
}
I don't think the second version does what you think it does. Socket.Connect returns information about the most recent IO command. You won't have a connection until EndConnect completes.
From my own experience, it looks like socket.EndConnect()
or socket.Close()
are irrelevant. If you failed to make a connection, the socket.Dispose
method (which will get called when the socket is destroyed) appears to be trying to disconnect anyway. When I call Dispose()
, EndConnect()
or Close()
, or simply put the socket into a USING
block, I get the same behaviour - a slow disconnection rather than an instant response. In fact, I haven't found a way to stop this happening even if I wanted it to.