【发布时间】:2013-02-06 01:42:39
【问题描述】:
我有一个List<Task<bool>>,我想并行枚举它,找到第一个要完成的任务,结果为true,而不是等待或观察任何其他仍待处理的任务的异常。
var tasks = new List<Task<bool>>
{
Task.Delay(2000).ContinueWith(x => false),
Task.Delay(0).ContinueWith(x => true),
};
我曾尝试使用 PLINQ 执行以下操作:
var task = tasks.AsParallel().FirstOrDefault(t => t.Result);
并行执行,但一旦找到令人满意的结果就不会返回。因为访问 Result 属性是阻塞的。为了使用 PLINQ 来实现这一点,我必须写下这个令人敬畏的声明:
var cts = new CancellationTokenSource();
var task = tasks.AsParallel()
.FirstOrDefault(t =>
{
try
{
t.Wait(cts.Token);
if (t.Result)
{
cts.Cancel();
}
return t.Result;
}
catch (OperationCanceledException)
{
return false;
}
} );
我编写了一个扩展方法,可以在任务完成时生成任务。
public static class Exts
{
public static IEnumerable<Task<T>> InCompletionOrder<T>(this IEnumerable<Task<T>> source)
{
var tasks = source.ToList();
while (tasks.Any())
{
var t = Task.WhenAny(tasks);
yield return t.Result;
tasks.Remove(t.Result);
}
}
}
// and run like so
var task = tasks.InCompletionOrder().FirstOrDefault(t => t.Result);
但感觉这很常见,有更好的方法。有什么建议吗?
【问题讨论】:
标签: c# task-parallel-library plinq