private async Task ConnectionWatchDog(TcpClient tcp)
        {
            while (!_connectionCancellation.IsCancellationRequested)
            {
                try
                {
                    using (tcp)
                        using (var nstream = tcp.GetStream())
                            using (var writer = new SocketWriter(nstream, _options.WriteBufferSize))
                                using (var reader = new SocketReader(nstream, _options.ReadBufferSize))
                                {
                                    RunInitializers(reader, writer);

                                    var tasks = new[]
                                    {
                                        Task.Run(() => ReadAsync(reader)),
                                        Task.Run(() => WriteAsync(writer)),
                                        _options.PingTimeout != Timeout.InfiniteTimeSpan ? Task.Run(() => TimeoutWatchdogAsync()) : new Task(() => {})
                                    };

                                    if (_interval != Timeout.InfiniteTimeSpan)
                                    {
                                        _pingTimer.Change(_interval, _interval); // start timer
                                    }
                                    _loadFactor = 1;
                                    OnConnection();

                                    await Task.WhenAny(tasks).ConfigureAwait(false);

                                    ThrowSocketExceptionIfExists(tasks);
                                }
                }
                catch (SocketException soex)
                {
                    // rotate endpoint
                    _currentEndpoint = (_currentEndpoint + 1) % _endpoints.Length;
                    _logger.Error(soex, "Connection {0} error. Switching endpoing.", _code);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "Connection {0} error.", _code);
                }

                _logger.Info("Connection {0} disconnected.", _code);
                _loadFactor = 100;
                _pending.CancelTokens();
                OnDisconnection();

                if (_connectionCancellation.IsCancellationRequested)
                {
                    continue;
                }

                tcp = new TcpClient();
                await ConnectWithTimeOut(tcp, _endpoints[_currentEndpoint]).ConfigureAwait(false);
            }
        }