【问题标题】:How to await tasks based on condition? [duplicate]如何根据条件等待任务? [复制]
【发布时间】:2014-08-06 06:14:26
【问题描述】:

我想知道GetDataFromLongRunningOp返回的结果是否至少有一个满足某个条件:

foreach (var item in list)
{
    var result = GetDataFromLongRunningOp(item);
    if (CheckCondition(result))
    {
        return true;
    }
}

return false;

如何为每个项目并行调用GetDataFromLongRunningOp,以减少查找答案所需的总时间?

编辑GetDataFromLongRunningOp 是一个异步方法。

【问题讨论】:

  • 我没有看到任何Taskawait 的任何使用。我错过了什么吗?

标签: c# asynchronous async-await


【解决方案1】:

使用Task.Run 异步运行GetDataFromLongRunningOp。使用TaskCompletionSource,当返回满足条件的结果时,将返回已完成的任务。如果没有结果满足条件,那么tcs.Task 将永远不会完成。您需要另一个等待所有任务完成的任务。所以,最后,您需要等待tcs.TaskTask.WhenAll 完成。

var result = false;

var tasks = new List<Task>();
var tcs = new TaskCompletionSource<bool>();

foreach (var item in list)
{
    var task = Task.Run(() => GetDataFromLongRunningOp(item))
        .ContinueWith(t =>
        {
            if (CheckCondition(t.Result))
            {
                result = true;
                tcs.TrySetResult(true);
            }
        });
    tasks.Add(task);
}

await Task.WhenAny(tcs.Task, Task.WhenAll(tasks));

return result;

【讨论】:

    【解决方案2】:

    假设你的工作是 CPU 密集型而不是 IO 密集型,你可以查看Parallel.ForEach:

    Parallel.ForEach(list, (item) => 
    {
        var result = GetDataFromLongRunningOp(item);
        if (CheckCondition(result))
        {
            return true;
        }
    });
    
    return false;
    

    请注意,您必须确保 GetDataFromLongRunningOp 是线程安全的,当然,基准测试您的代码以确保并行运行不会超过成本。

    【讨论】:

      猜你喜欢
      • 2020-05-13
      • 1970-01-01
      • 2013-08-06
      • 1970-01-01
      • 2010-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多