private async Task Flush(int sequence, CancellationToken token = default(CancellationToken)) { using (await _flushLock.LockAsync(token).ConfigureAwait(false)) { string chunk; bool increment = false; lock (_builder) { chunk = _builder.ToString(); if ((sequence > -1) && string.IsNullOrEmpty(chunk)) { return; } _builder.Clear(); if (_sequenceId < 0) { return; } if (sequence < 0) { _sequenceId = sequence; } else { increment = true; } } NamedPipeConnection connection = _connection; if (connection != null) { await connection.Send(new CommandResponse(ID, _sequenceId, chunk), token).ConfigureAwait(false); } if (increment) { lock (_builder) _sequenceId++; } } }
/// <summary> /// Initializes a new instance of the <see cref="ConnectedCommand" /> class. /// </summary> /// <param name="connectionGuid">The connection unique identifier.</param> /// <param name="service">The service.</param> /// <param name="connection">The connection.</param> /// <param name="request">The request.</param> /// <param name="token">The cancellation token.</param> public ConnectedCommand( Guid connectionGuid, [NotNull] BaseService service, [NotNull] NamedPipeConnection connection, [NotNull] CommandRequest request, CancellationToken token = default(CancellationToken)) { ConnectionGuid = connectionGuid; _connection = connection; _request = request; _cancellationTokenSource = token.ToCancelable(); ID = _request.ID; token = _cancellationTokenSource.Token; Task.Run( async() => { try { do { // ReSharper disable once PossibleNullReferenceException await Task.Delay(250, token).ConfigureAwait(false); if (token.IsCancellationRequested) { return; } await Flush(0, token).ConfigureAwait(false); } while (true); } catch (TaskCanceledException) { } }, token); // Kick of task to run command. Task.Run( async() => { Exception exception = null; bool cancelled = false; try { await service.ExecuteAsync(ConnectionGuid, _request.CommandLine, this, token) .ConfigureAwait(false); if (!token.IsCancellationRequested) { await Flush(-1, token).ConfigureAwait(false); } else { cancelled = true; } } catch (OperationCanceledException) { cancelled = true; } catch (Exception e) { exception = e; } if (cancelled) { using (await _flushLock.LockAsync(token).ConfigureAwait(false)) { try { using (CancellationTokenSource cts = Constants.FireAndForgetTokenSource) await connection.Send( new CommandCancelResponse( _cancelRequest != null ? _cancelRequest.ID : Guid.Empty, ID), cts.Token) .ConfigureAwait(false); } catch (OperationCanceledException) { } return; } } if (exception != null) { try { await Flush(0, token).ConfigureAwait(false); _builder.Append(exception.Message); await Flush(-2, token).ConfigureAwait(false); } // ReSharper disable once EmptyGeneralCatchClause catch { } } Dispose(true); }, token); }