private async Task ConnectAsync(CancellationTokenSource reconnectCancelToken)
        {
            _connectionCancelToken?.Dispose();
            _combinedCancelToken?.Dispose();
            _connectionCancelToken = new CancellationTokenSource();
            _combinedCancelToken   = CancellationTokenSource.CreateLinkedTokenSource(_connectionCancelToken.Token, reconnectCancelToken.Token);
            CancelToken            = _combinedCancelToken.Token;

            _connectionPromise = new TaskCompletionSource <bool>();
            State = ConnectionState.Connecting;
            await _logger.InfoAsync("Connecting").ConfigureAwait(false);

            try
            {
                var readyPromise = new TaskCompletionSource <bool>();
                _readyPromise = readyPromise;

                //Abort connection on timeout
                var cancelToken = CancelToken;
                var _           = Task.Run(async() =>
                {
                    try
                    {
                        await Task.Delay(_connectionTimeout, cancelToken).ConfigureAwait(false);
                        readyPromise.TrySetException(new TimeoutException());
                    }
                    catch (OperationCanceledException) { }
                });

                try
                {
                    await _onConnecting().ConfigureAwait(false);
                }
                catch (TaskCanceledException ex)
                {
                    Exception innerEx = ex.InnerException ?? new OperationCanceledException("Failed to connect.");
                    Error(innerEx);
                    throw innerEx;
                }

                await _logger.InfoAsync("Connected").ConfigureAwait(false);

                State = ConnectionState.Connected;
                await _logger.DebugAsync("Raising Event").ConfigureAwait(false);

                await _connectedEvent.InvokeAsync().ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Error(ex);
                throw;
            }
        }
        private async Task DisconnectAsync(Exception ex, bool isReconnecting)
        {
            if (State == ConnectionState.Disconnected)
            {
                return;
            }
            State = ConnectionState.Disconnecting;
            await _logger.InfoAsync("Disconnecting").ConfigureAwait(false);

            await _onDisconnecting(ex).ConfigureAwait(false);

            await _disconnectedEvent.InvokeAsync(ex, isReconnecting).ConfigureAwait(false);

            State = ConnectionState.Disconnected;
            await _logger.InfoAsync("Disconnected").ConfigureAwait(false);
        }