TcpClient.EndConnect throws NullReferenceException when socket is closed

Viewed 6853

I am trying to connect to my server with a TcpClient.BeginConnect / TcpClient.EndConnect combo. However, some things don't work as they should.

The scenario is as follows:

  • Call to the TcpClient.BeginConnect
  • Server is intentionally offline (for testing purposes) - thus no connection can be made.
  • I close the application (client.Close() gets called in the process which closes the socket which in turn stops the async operation)
  • TcpClient connection callback method happens giving IAsyncResult
  • Call to the TcpClient.EndConnect method with the given IAsyncResult
  • NullReferenceException happens on EndConnect (?)
  • Since the last form (window) was closed, the app should exit - however it does not, at least not until BeginConnect operation completes (which is strange, as callback has already been called).

exception

What happens here is that a NullReferenceException is caught. As you can see from the picture above, neither client nor ar are null. The problem is that the MSDN documentation for the EndConnect does not mention the case in which this exception is thrown.

So basically, I have no idea what is going on. The problem is that I am forced to wait for the app to close (as if the connection operation still waits for a timeout). If a server is online, it connects and disconnects just fine.

What does NullReferenceException in this context mean? How to avoid BeginConnect operation to block the application closing in case the connection can't be established?


Additional notes (requested in comments):

Here is the code to create the client (client is a member variable:

public void Connect()
{
    try
    {
        lock (connectionAccess)
        {
            if (State.IsConnectable())
            {
                // Create a client
                client = new TcpClient();
                client.LingerState = new LingerOption(false, 0);
                client.NoDelay = true;

                State = CommunicationState.Connecting;

                client.BeginConnect(address, port, onTcpClientConnectionEstablished, null);
            }
            else
            {
                // Ignore connecting request if a connection is in a state that is not connectable 
            }
        }
    }
    catch
    {
        Close(true);
    }
}

Also the Close method:

public void Close(bool causedByError)
{
    lock (connectionAccess)
    {
        // Close the stream
        if (clientStream != null)
            clientStream.Close();

        // Close the gateway
        if (client != null)
            client.Close();

        // Empty the mailboxes
        incomingMailbox.Clear();
        outgoingMailbox.Clear();

        State = causedByError ? CommunicationState.CommunicationError : CommunicationState.Disconnected;
    }
}
4 Answers
Related