/// <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); }