如何安排条件ContinueWith

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,是否抛出异常?或者是否有一些我没想到的简单分支机制?

Ree*_*sey 9

这里一个很好的选择是使用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>另外制作一个版本,以及处理任务上的故障/取消状态.话虽如此,它应该正常运作.


Jon*_*eet 5

如果有错误,您应该考虑相应地使您的任务出错。然后你可以TaskContinuationOptions.OnlyOnRanToCompletionContinueWith通话中使用等。

在任务生命周期结束时,基本上有三种可能的状态:

  • 随机完成
  • 取消
  • 故障

您可以ContinueWith应用这些状态的任何合理组合,并且如果您想根据错误、成功、取消等执行不同的操作,您可以将不同的延续附加到同一个父任务。