c# - 使用 TPL 的推测执行

标签 c# task-parallel-library plinq

我有一个 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);

但感觉这很常见,所以有更好的方法。有什么建议吗?

最佳答案

也许是这样的?

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;

关于c# - 使用 TPL 的推测执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14720225/

相关文章:

c# - Microsoft 报告导出为 pdf 的 rdlc 性能问题

c# - 询问 ActiveDirectory 计算机是否是组的成员

c# - 限制同时执行任务的数量

c# - 将线程本地数据与 PLINQ AsParallel() 一起使用?

c# - PLINQ性能问题

c# - Entity Framework 4.1 RC : Code First EntityTypeConfiguration inheritance issue

c# - Entity Framework 中的实体是否可以继承未映射到表的实体?

task-parallel-library - TPL DataFlow-按持续时间或阈值进行批处理

c# - 从同步代码调用异步方法并阻塞直到任务完成的正确方法是什么?

c# - 在 foreach 中访问 LINQ Select 中使用的值