如何根据条件等待任务?

3

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

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

return false;

我怎么能同时对每个项目调用GetDataFromLongRunningOp,以减少找到答案所需的总时间? 编辑GetDataFromLongRunningOp是一个异步方法。

1
我没看到任何 Task 或者使用了 await,我有什么遗漏的吗? - Yuval Itzchakov
2个回答

5

使用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;

1
假设您的工作是CPU密集型而不是IO密集型,您可以考虑使用Parallel.ForEach
Parallel.ForEach(list, (item) => 
{
    var result = GetDataFromLongRunningOp(item);
    if (CheckCondition(result))
    {
        return true;
    }
});

return false;

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接