【问题标题】:TPL wait for task to complete with a specific return valueTPL 等待任务以特定返回值完成
【发布时间】:2017-01-05 21:18:14
【问题描述】:

我想向 X 个不同的 Web 服务发出请求,它们将分别返回 truefalse

这些任务应该并行执行,我想等待第一个真实值完成的任务。当我收到一个真值时,我不希望等待其他任务完成。

在下面的示例中,t1 不应等待,因为t3 先完成并返回true

var t1 = Task.Run<bool>(() =>
{
    Thread.Sleep(5000);
    Console.WriteLine("Task 1 Excecuted");
    return true;
}, cts.Token);

var t2 = Task.Run<bool>(() =>
{
    Console.WriteLine("Task 2 Executed");
    return false;
}, cts.Token);

var t3 = Task.Run<bool>(() =>
{
    Thread.Sleep(2000);
    Console.WriteLine("Task 3 Executed");
    return true;
}, cts.Token);

基本上我正在寻找带有谓词的Task.WhenAny,当然它不存在。

【问题讨论】:

  • @AdamPlocher 这个问题在async-await 环境中不太相关。
  • 我感觉这里某处有一个 TPL DataFlow 解决方案,希望我有时间坐下来玩一下!

标签: c# .net task-parallel-library async-await


【解决方案1】:

您可以简单地多次使用Task.WhenAny 和谓词,直到“正确”任务出现

async Task<T> WhenAny<T>(IEnumerable<Task<T>> tasks, Func<T, bool> predicate)
{
    var taskList = tasks.ToList();
    Task<T> completedTask = null;
    do
    {
        completedTask = await Task.WhenAny(taskList);
        taskList.Remove(completedTask);
    } while (!predicate(await completedTask) && taskList.Any());

    return completedTask == null ? default(T) : await completedTask;
}

【讨论】:

    【解决方案2】:

    一种选择是使用Reactive Extensions。让我们假设您有一组任务。可能是您在问题中提到的任务:

    var tasks = new[] { t1, t2, t3 };
    

    要并行执行任务并在第一个任务返回 true 时返回,请使用以下表达式:

    var result = await tasks
      .Select(t => t.ToObservable())
      .Merge()
      .FirstOrDefaultAsync(success => success);
    

    任务被转换成可观察的序列,每个在任务完成时“触发”一次。然后将这些序列合并为一个序列,然后将其“转换”回可以使用谓词等待的东西。如果需要,您可以使用更复杂的谓词代替success =&gt; success

    之后,如果您使用CancellationTokenSource,则可以取消剩余的未完成任务:

    cts.Cancel();
    

    变量result 现在将是truefalse,并且所有剩余的任务都已收到取消信号。

    如果您想使用示例任务对此进行测试,您必须稍微修改它们以使用 Task.Delay 而不是 Thread.Sleep 来取消任务:

    var t1 = Task.Run<bool>(async () =>
    {
        await Task.Delay(TimeSpan.FromSeconds(1), cts.Token);
        Console.WriteLine("Task 1 Excecuted");
        return false;
    }, cts.Token);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-15
      • 1970-01-01
      相关资源
      最近更新 更多