将任务排序为完成顺序

时间:2013-06-05 11:41:49

标签: c# asynchronous task-parallel-library

我看到Jon Skeet在大约一年前发表演讲,他在那里展示了一个C#5的片段,它将获取任务列表并按照他们完成的顺序返回。

它使用了async / await和WhenAny并且很漂亮,但我不能为我的生活记住它是如何工作的。现在我需要它。

我希望弄清楚如何使用类似于此的签名创建方法。

Task<IEnumerable<T>> InOrderOfCompletion<T>(IEnumerable<T> tasks) where T : Task

可以使用如下:

public async Task<int> DelayedInt(int i)
{
    await Task.Delay(i*100);
    return i;
}

[Test]
public async void Test()
{
    Task<int>[] tasks = new[] {5, 7, 1, 3, 2, 6, 4}.Select(DelayedInt).ToArray();
    IEnumerable<Task<int>> ordered = await InOrderOfCompletion(tasks);

    Assert.That(ordered.Select(t => t.Result).ToArray(), Is.EqualTo(new [] {1,2,3,4,5,6,7}));
}

我想出了以下内容,但感觉并不像我记得的那么简单

    async Task<IEnumerable<T>> InOrderOfCompletion<T>(IEnumerable<T> tasks) where T : Task
    {
        HashSet<Task> taskSet = new HashSet<Task>(tasks);
        List<T> results = new List<T>();
        while(taskSet.Count > 0)
        {
            T complete = (T) await Task.WhenAny(taskSet);
            taskSet.Remove(complete);
            results.Add(complete);
        }
        return results;
    }

有人记得知道我所指的片段或者如何改进它吗?

1 个答案:

答案 0 :(得分:11)

Jon SkeetStephen Touband I的方法略有不同。如果您不想自己编写,我的是available via NuGet

实际上,关键是避免 Task.WhenAny,因为这会将算法从O(N)变为O(N ^ 2)。