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