Trier les tâches en ordre d’achèvement

J’ai vu Jon Skeet donner une conférence il y a environ un an, où il a montré un extrait de code C # 5 qui prendrait une liste de tâches et les retournerait dans l’ordre dans lequel elles auraient été accomplies.

Il utilisait async / wait et WhenAny et était très beau mais je ne peux pas me rappeler comment cela fonctionnait. Maintenant j’en ai besoin.

J’espère comprendre comment créer une méthode avec une signature semblable à celle-ci.

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

Et pourrait être utilisé comme suit:

 public async Task DelayedInt(int i) { await Task.Delay(i*100); return i; } [Test] public async void Test() { Task[] tasks = new[] {5, 7, 1, 3, 2, 6, 4}.Select(DelayedInt).ToArray(); IEnumerable<Task> ordered = await InOrderOfCompletion(tasks); Assert.That(ordered.Select(t => t.Result).ToArray(), Is.EqualTo(new [] {1,2,3,4,5,6,7})); } 

Je viens avec ce qui suit, mais cela ne semble pas aussi simple que je me souvienne

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

Est-ce que quelqu’un se souvient de connaître l’extrait auquel je fais référence ou comment améliorer cela?

Jon Skeet , Stephen Toub et moi avons tous une approche légèrement différente. Le mien est disponible via NuGet si vous ne voulez pas écrire le vôtre.

En fait, la clé est d’ éviter Task.WhenAny car cela transformera l’algorithme de O (N) en O (N ^ 2).