Freigeben über


Task-based Asynchronous Pattern - WhenSome

I don't think this is the most common case, but sometimes you have a large number of tasks and you're interested in the result from a few of them, but not all of them. Here are some extension methods to wait for some tasks (no pun intended):

  1: public static Task WhenSome(int target, params Task[] tasks)
 2: {
 3:     return TaskExtensions.WhenSome(target, new Progress<int>(), tasks);
 4: }
 5:  
 6: public static Task<T[]> WhenSome<T>(int target, params Task<T>[] tasks)
 7: {
 8:     return TaskExtensions.WhenSome(target, new Progress<T>(), tasks);
 9: }
 10:  
 11: public async static Task WhenSome(
 12:     int target, IProgress<int> progress, params Task[] tasks)
 13: {
 14:     if (target > tasks.Length)
 15:     {
 16:         throw new ArgumentOutOfRangeException("target");
 17:     }
 18:  
 19:     var remainingTasks = new List<Task>(tasks);
 20:     int completedTasks = 0;
 21:     while (completedTasks < target)
 22:     {
 23:         await Task.WhenAny(tasks);
 24:         var stillRemainingTasks = new List<Task>(remainingTasks.Count - 1);
 25:         for (
 26:             int i = 0; 
 27:             i < remainingTasks.Count && completedTasks < target; 
 28:             i++)
 29:         {
 30:             if (remainingTasks[i].IsCompleted)
 31:             {
 32:                 progress.Report(++completedTasks);
 33:             }
 34:             else
 35:             {
 36:                 stillRemainingTasks.Add(remainingTasks[i]);
 37:             }
 38:         }
 39:  
 40:         remainingTasks = stillRemainingTasks;
 41:     }
 42: }
 43:  
 44: public async static Task<T[]> WhenSome<T>(
 45:     int target, IProgress<T> progress, params Task<T>[] tasks)
 46: {
 47:     if (target > tasks.Length)
 48:     {
 49:         throw new ArgumentOutOfRangeException("target");
 50:     }
 51:  
 52:     var remainingTasks = new List<Task<T>>(tasks);
 53:     var result = new List<T>(target);
 54:     while (result.Count < target)
 55:     {
 56:         await Task.WhenAny(tasks);
 57:         var stillRemainingTasks = new List<Task<T>>(
 58:             remainingTasks.Count - 1);
 59:         for (
 60:             int i = 0; 
 61:             i < remainingTasks.Count && result.Count < target; i++)
 62:         {
 63:             if (remainingTasks[i].IsCompleted)
 64:             {
 65:                 result.Add(remainingTasks[i].Result);
 66:                 progress.Report(remainingTasks[i].Result);
 67:             }
 68:             else
 69:             {
 70:                 stillRemainingTasks.Add(remainingTasks[i]);
 71:             }
 72:         }
 73:  
 74:         remainingTasks = stillRemainingTasks;
 75:     }
 76:  
 77:     return result.ToArray();
 78: }