// Called when the DNS query completes (either synchronously or asynchronously). Checks for failure and // starts the first connection attempt if it succeeded. Returns true if the operation will be asynchronous, // false if it has failed synchronously. private bool DoDnsCallback(IAsyncResult result, bool sync) { Exception exception = null; lock (_lockObject) { // If the connection attempt was canceled during the dns query, the user's callback has already been // called asynchronously and we simply need to return. if (_state == State.Canceled) { return(true); } if (_state != State.DnsQuery) { NetEventSource.Fail(this, "MultipleConnectAsync.DoDnsCallback(): Unexpected object state"); } try { _addressList = Dns.EndGetHostAddresses(result); if (_addressList == null) { NetEventSource.Fail(this, "MultipleConnectAsync.DoDnsCallback(): EndGetHostAddresses returned null!"); } } catch (Exception e) { _state = State.Completed; exception = e; } // If the dns query succeeded, try to connect to the first address if (exception == null) { _state = State.ConnectAttempt; _internalArgs = new SocketAsyncEventArgs(); _internalArgs.Completed += InternalConnectCallback; _internalArgs.CopyBufferFrom(_userArgs); exception = AttemptConnection(); if (exception != null) { // There was a synchronous error while connecting _state = State.Completed; } } } // Call this outside of the lock because it might call the user's callback. if (exception != null) { return(Fail(sync, exception)); } else { return(true); } }