/// <summary> /// Connect. /// </summary> public Task <MTProtoConnectResult> Connect(CancellationToken cancellationToken) { return(Task.Run( async() => { var result = MTProtoConnectResult.Other; using (await _connectionLock.LockAsync(cancellationToken)) { if (_state == MTProtoConnectionState.Connected) { result = MTProtoConnectResult.Success; return result; } Debug.Assert(_state == MTProtoConnectionState.Disconnected); try { _state = MTProtoConnectionState.Connecting; Console.WriteLine("Connecting..."); await _clientTransport.ConnectAsync(cancellationToken).ToObservable().Timeout(DefaultConnectTimeout); _connectionCts = new CancellationTokenSource(); _connectionCancellationToken = _connectionCts.Token; Console.WriteLine("Connected."); result = MTProtoConnectResult.Success; } catch (TimeoutException) { result = MTProtoConnectResult.Timeout; Console.WriteLine( string.Format( "Failed to connect due to timeout ({0}s).", DefaultConnectTimeout.TotalSeconds)); } catch (Exception e) { result = MTProtoConnectResult.Other; Console.WriteLine("Failed to connect.: " + e); } finally { switch (result) { case MTProtoConnectResult.Success: _state = MTProtoConnectionState.Connected; break; case MTProtoConnectResult.Timeout: case MTProtoConnectResult.Other: _state = MTProtoConnectionState.Disconnected; break; default: throw new ArgumentOutOfRangeException(); } } } return result; }, cancellationToken)); }