2013-06-05 105 views
3

我看到Jon Skeet在一年多前發表了一個演講,他展示了C#5的片段,該片段將列出任務並按照它們完成的順序返回。根據完成順序排序任務

它使用了異步/等待和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; 
    } 

有人記得知道我的片段指的是或如何改善?

回答

10

Jon Skeet,Stephen Toub,and I都有稍微不同的方法。如果你不想自己寫,我的是available via NuGet

其實,關鍵是要避免Task.WhenAny,因爲這會將算法從O(N)變成O(N^2)。

+0

謝謝,這正是我之後的事情,非常聰明的東西。 – chillitom