I have List<Task<bool>>one that I want to list in parallel to find the first task with the result trueand not wait or watch for exceptions for any of the remaining tasks.
var tasks = new List<Task<bool>>
{
Task.Delay(2000).ContinueWith(x => false),
Task.Delay(0).ContinueWith(x => true),
};
I tried using PLINQ to do something like:
var task = tasks.AsParallel().FirstOrDefault(t => t.Result);
It is executed in parallel, but does not return as soon as it finds a satisfactory result. because access to the Result property is blocked. In order for this to work using PLINQ, I would have to write this serious expression:
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 wrote an extension method that gives tasks as they are completed.
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);
}
}
}
var task = tasks.InCompletionOrder().FirstOrDefault(t => t.Result);
But it seems that this is something in common, that there is a better way. Suggestions?
source
share