Tor*_*mod 11 c# continuations asynchronous task-parallel-library c#-4.0
我在一堆LINQ查询上有一些GUI.查询需要一些时间来执行,所以我希望GUI能够响应并显示busyindicators和进度条.许多查询都是检查数据中存在的某些条件.如果查询返回空结果,则应用程序将继续下一个查询.如果它返回结果,则返回集将具有严重性"警告"或"错误".如果是警告,则继续执行.如果是错误,它应该停止.
许多代码使用线程池和GUI播放"乒乓".准码:
TaskFactory.StartNew(()=>
{
Run in background
}.ContinueInGui(()=>
{
Update something
}).ContinueInBackground(()=>
{
Do more work;
}).ContinueInGui(()=> etc etc
Run Code Online (Sandbox Code Playgroud)
这很整洁.但是,如果在数据中发现错误,我不会看到如何插入条件来执行不同的延续路径或中断连续链.
ContinueWithIf没有方法(谓词,委托{},TaskScheduler)我是否使用TaskCancellation,是否抛出异常?或者是否有一些我没想到的简单分支机制?
这里一个很好的选择是使用a CancelationTokenSource
,如果你想"破坏"你的延续链,只需将其标记为取消.通过在后续任务中包含TaskContinuationOptions.NotOnCanceledContinueWith
,您可以通过将其标记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;
}
Run Code Online (Sandbox Code Playgroud)
当然,你可能想要Task<T>
另外制作一个版本,以及处理任务上的故障/取消状态.话虽如此,它应该正常运作.
如果有错误,您应该考虑相应地使您的任务出错。然后你可以TaskContinuationOptions.OnlyOnRanToCompletion
在ContinueWith
通话中使用等。
在任务生命周期结束时,基本上有三种可能的状态:
您可以ContinueWith
应用这些状态的任何合理组合,并且如果您想根据错误、成功、取消等执行不同的操作,您可以将不同的延续附加到同一个父任务。