我在一堆LINQ查询上有一些GUI。查询需要一些时间来执行,所以我希望GUI能够响应并显示busyindicators和进度条。许多查询都是检查数据中存在的某些条件。如果查询返回空结果,则应用程序将继续下一个查询。如果它返回结果,则返回集将具有严重性"警告"或"错误"。如果是警告,则继续执行。如果是错误,它将停止。
许多代码播放"乒乓球"使用线程池和GUI。准码:
TaskFactory.StartNew(()=>
{
Run in background
}.ContinueInGui(()=>
{
Update something
}).ContinueInBackground(()=>
{
Do more work;
}).ContinueInGui(()=> etc etc
这很整洁。但是,如果在数据中发现错误,我不知道如何插入条件来执行不同的延续路线或中断连续链。
没有ContinueWithIf方法(谓词,委托{},TaskScheduler) 我是否使用TaskCancellation,是否会抛出异常?或者是否有一些我没想过的简单分支机制?
答案 0 :(得分:9)
这里的一个好选择是使用CancelationTokenSource
,如果你想“破坏”你的连续链,只需将其标记为取消。通过在ContinueWith
中添加TaskContinuationOptions.NotOnCanceled作为后续任务,您可以通过将CancelationTokenSource
标记为已取消来随时安排这些任务。
如果你真的想使用谓词,而不是在main方法中设置continuation,你需要制作一个自定义方法来为你处理这个问题。这可以通过使用附加延续的扩展方法来完成 - 延续可以检查谓词,并在适当时触发连续。这看起来像是:
public static Task ContinueWithIf(this Task task, Func<bool> predicate, Action<Task> continuation, TaskScheduler scheduler)
{
var tcs = new TaskCompletionSource<object>();
task.ContinueWith( t =>
{
if (predicate())
{
new TaskFactory(scheduler).StartNew(
() =>
{
continuation(task);
tcs.SetResult(null);
});
}
else
{
tcs.TrySetCanceled();
}
});
return tcs.Task;
}
当然,你可能想要为Task<T>
创建一个版本,以及处理任务上的故障/取消状态。话虽如此,它应该正常运作。
答案 1 :(得分:4)
如果有错误,您应该考虑相应地使您的任务出错。然后,您可以在ContinueWith
来电中使用TaskContinuationOptions.OnlyOnRanToCompletion
等。
基本上,在任务结束时有三种可能的状态:
你可以让ContinueWith
适用于这些状态的任何合理组合,如果你想根据错误与成功和取消等做不同的事情,你可以为同一个父任务附加不同的延续。