私は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);
しかし、これはより良い方法があるほど一般的なことのように感じます. 提案?