private async Task ProccessSubscription(TaskCompletionSource <object> successfullyConnected) { try { _proccessingCts.Token.ThrowIfCancellationRequested(); using (var context = new JsonOperationContext(4096, 1024)) { using (var tcpStream = await ConnectToServer().ConfigureAwait(false)) using (var parser = context.ParseMultiFrom(tcpStream)) { _proccessingCts.Token.ThrowIfCancellationRequested(); var readObjectTask = ReadNextObject(parser); var done = await Task.WhenAny(readObjectTask, _disposedTask.Task).ConfigureAwait(false); if (done == _disposedTask.Task) { return; } var connectionStatus = await readObjectTask.ConfigureAwait(false); if (_proccessingCts.IsCancellationRequested) { return; } AssertConnectionState(connectionStatus); #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed Task.Run(() => successfullyConnected.TrySetResult(null)); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed readObjectTask = ReadNextObject(parser); if (_proccessingCts.IsCancellationRequested) { return; } var incomingBatch = new List <BlittableJsonReaderObject>(); long lastReceivedEtag = 0; while (_proccessingCts.IsCancellationRequested == false) { BeforeBatch(); bool endOfBatch = false; while (endOfBatch == false && _proccessingCts.IsCancellationRequested == false) { done = await Task.WhenAny(readObjectTask, _disposedTask.Task).ConfigureAwait(false); if (done == _disposedTask.Task) { break; } var receivedMessage = await readObjectTask.ConfigureAwait(false); if (_proccessingCts.IsCancellationRequested) { break; } readObjectTask = ReadNextObject(parser); if (_proccessingCts.IsCancellationRequested) { break; } switch (receivedMessage.Type) { case SubscriptionConnectionServerMessage.MessageType.Data: incomingBatch.Add(receivedMessage.Data); break; case SubscriptionConnectionServerMessage.MessageType.EndOfBatch: endOfBatch = true; break; case SubscriptionConnectionServerMessage.MessageType.Confirm: AfterAcknowledgment(); AfterBatch(incomingBatch.Count); incomingBatch.Clear(); break; case SubscriptionConnectionServerMessage.MessageType.Error: switch (receivedMessage.Status) { case SubscriptionConnectionServerMessage.ConnectionStatus.Closed: throw new SubscriptionClosedException(receivedMessage.Exception ?? string.Empty); default: throw new Exception( $"Connection terminated by server. Exception: {receivedMessage.Exception ?? "None"}"); } default: throw new ArgumentException( $"Unrecognized message '{receivedMessage.Type}' type received from server"); } } foreach (var curDoc in incomingBatch) { NotifySubscribers(curDoc, out lastReceivedEtag); } SendAck(lastReceivedEtag, tcpStream); } } } } catch (OperationCanceledException) { } catch (Exception ex) { if (_proccessingCts.Token.IsCancellationRequested == false) { InformSubscribersOnError(ex); } throw; } }