我正在使用命令行实用程序开发内部应用程序来控制PDF文档的操作。我正在尝试构建一个CommandManager类,允许一次运行多个操作,允许它们被取消等等。
我有一个包装器对象(PdfCommandTask),用于管理我想要执行的命令,取消源和任务。然后,我会在我的UI中保留这些列表。 ProcessAsync是一个基于任务的解决方案,用于运行我在此处找到的Process对象:
ProcessStartInfo hanging on "WaitForExit"? Why?
我对TPL相当苛刻,我遇到了一个问题,即当我取消任务时,下面代码中的延续不会触发...它会触发正常任务完成或不同的错误条件。
在调试器中,它遵循Exception catch路径,设置我的结果对象,并点击第一个任务的return语句......但是继续进行而不进入延续并移出方法。
我经历了几次迭代并阅读了很多帖子,但我还没弄清楚我的问题。任何想法将不胜感激。
注意:我意识到AggregateException / Exception处理可能是多余的,我只是试图在我的测试中覆盖我的基础。
感谢。
public void Execute(PdfCommand command)
{
PdfCommandResult result = command.Valid();
if (!result.Success)
{
CommandCompleted?.Invoke(this, result);
return;
}
command.BuildCommands();
var cmdTask = new PdfCommandTask(command);
var token = cmdTask.CancelTokenSource.Token;
// Add the task to the task list
CommandList.Add(cmdTask);
cmdTask.Task = Task.Run<PdfCommandResult>(async () =>
{
Debug.Print("Spinning up task...");
var pdfResult = new PdfCommandResult();
List<Task> taskList = new List<Task>();
foreach (var cmd in command.Commands)
{
var procTask = ProcessAsync.StartProcess(Pdftk, cmd, cmdTask.CancelTokenSource, PdftkPath);
taskList.Add(procTask);
}
try
{
if (token.IsCancellationRequested)
token.ThrowIfCancellationRequested();
await Task.WhenAll(taskList);
}
catch (AggregateException e)
{
Debug.Print("AggregateException thrown.");
if (e.InnerException is OperationCanceledException)
pdfResult = new PdfCommandResult("The task was cancelled.");
else
pdfResult = new PdfCommandResult("The task faulted... Error: " + e.InnerException);
}
catch (Exception e)
{
Debug.Print("Exception thrown.");
if (e is OperationCanceledException)
pdfResult = new PdfCommandResult("The task was cancelled.");
else
pdfResult = new PdfCommandResult("The task faulted... Error: " + e);
}
return pdfResult;
}, token).ContinueWith((prevTask) =>
{
Debug.Print("ContinueWith fired.");
// Get the previous task result
result = prevTask.Result;
// Remove the task from the task list
CommandList.Remove(cmdTask);
// Let anyone listening know that the command completed (it may have been cancelled or faulted)
CommandCompleted?.Invoke(this, result);
}, token, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}