/// <summary> /// Executes proccesses asynchronously and return the <see cref="RunResults"/> instance. /// </summary> /// <returns><see cref="RunResults"/> instance with the results of the execution.</returns> public Task <RunResults> StartAsync() { if (disposed) { throw new ObjectDisposedException(nameof(ProcessRunner)); } if (CurrentTask == null || CurrentTask.IsCompleted) { messageFormatter.Clear(); bool retrieveOutput = !(messageFormatter is NoMessagesMessageFormatter); var concurrentDataReceiver = retrieveOutput ? new ConcurrentDataReceiver(this) : null; var processCollection = processCreator.CreateProcesses(concurrentDataReceiver); var tasks = processCollection.Select(process => RunProcess(process, retrieveOutput)); var whenAllTask = Task.WhenAll(tasks); if (concurrentDataReceiver == null) { CurrentTask = whenAllTask.ContinueWith(task => messageFormatter.GetRunResults()); } else { var ctrCancellationToken = new CancellationTokenSource(); var outputDataReceiverTask = concurrentDataReceiver.Run(ctrCancellationToken.Token); outputDataReceiverTask.ContinueWith(task => ctrCancellationToken.Dispose()); CurrentTask = whenAllTask.ContinueWith(task => { ctrCancellationToken.Cancel(); outputDataReceiverTask.Wait(); return(messageFormatter.GetRunResults()); }); } return(CurrentTask); } else { throw new InvalidOperationException(nameof(ProcessRunner)); } }