使用TPL推测执行 [英] Speculative execution using the TPL
问题描述
我有一个列表<任务<布尔>>
,我想在平行枚举找到的第一个任务与的结果来完成真正
,而不是等待或任何其他任务仍有待观察异常。
I have a List<Task<bool>>
that I want to enumerate in parallel finding the first task to complete with a result of true
and not waiting for or observe exceptions on any of the other tasks still pending.
var tasks = new List<Task<bool>>
{
Task.Delay(2000).ContinueWith(x => false),
Task.Delay(0).ContinueWith(x => true),
};
我曾尝试使用PLINQ做这样的事情:
I have tried to use PLINQ to do something like:
var task = tasks.AsParallel().FirstOrDefault(t => t.Result);
哪个并行执行,但只要它找到一个令人满意的结果不会返回。因为访问Result属性是阻塞。为了使这种使用PLINQ的工作,我不得不写这aweful语句:
Which executes in parallel, but doesn't return as soon as it finds a satisfying result. because accessing the Result property is blocking. In order for this to work using PLINQ, I'd have to write this aweful statement:
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;
}
} );
我已经写了能产生任务,他们完成像这样的扩展方法。
I've written up an extension method that yields tasks as they complete like so.
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);
但感觉这是很常见的东西,有一个更好的办法。建议?
But it feels like this is something common enough that there is a better way. Suggestions?
推荐答案
也许这样的事情?
var tcs = new TaskCompletionSource<Task<bool>>();
foreach (var task in tasks)
{
task.ContinueWith((t, state) =>
{
if (t.Result)
{
((TaskCompletionSource<Task<bool>>)state).TrySetResult(t);
}
},
tcs,
TaskContinuationOptions.OnlyOnRanToCompletion |
TaskContinuationOptions.ExecuteSynchronously);
}
var firstTaskToComplete = tcs.Task;
这篇关于使用TPL推测执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!