将任务按完成顺序排序

本文关键字:顺序 排序 任务 | 更新日期: 2023-09-27 18:17:15

我看到Jon Skeet在大约一年前做了一个演讲,他展示了一个c# 5的片段,它可以接受任务列表,并按照任务完成的顺序返回它们。

它使用了async/await和WhenAny,非常漂亮,但我已经记不起它是如何工作的了。现在我需要它了

我希望弄清楚如何创建一个签名类似于这个方法..

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

And的用法如下:

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;
    }

有谁记得我提到的片段或者如何改进它吗?

将任务按完成顺序排序

Jon Skeet, Stephen Toub和我都有稍微不同的方法。如果你不想自己写的话,我的可以通过NuGet获得。

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