I couldn't resist to create a method to deal with a scenario even less common than WhenSome. The crazy scenario here is that you have N tasks of type Task<T> and you want to return when a random task completes. The easiest way to do this is to just pick a random task and wait for it like this:

 1: public static Task<T> WhenRandom<T>(params Task<T>[] tasks)
 2: {
 3:     var random = new Random();
 4:     return (from task in tasks
 5:             orderby random.Next()
 6:             select task).FirstOrDefault();
 7: }

However what if you want to be able to cancel the WhenRandom call you need to be a little more creative I guess:

 8: public static async Task<T> WhenRandom<T>(CancellationToken cancellationToken,
 9:                                           params Task<T>[] tasks)
 10: {
 11:     var random = new Random().Next(0, tasks.Length);
 12:     var remainingTasks = new List<Task<T>>(tasks);
 13:     while (remainingTasks.Count > 0)
 14:     {
 15:         await Task.WhenAny(remainingTasks);
 16:         for (int i = 0; i < remainingTasks.Count; i++)
 17:         {
 18:             if (remainingTasks[i].IsCompleted)
 19:             {
 20:                 if (random-- == 0)
 21:                 {
 22:                     return await remainingTasks[i];
 23:                 }
 24:  
 25:                 remainingTasks.RemoveAt(i--);
 26:             }
 27:         }
 28:  
 29:         cancellationToken.ThrowIfCancellationRequested();
 30:     }
 31:  
 32:     return default(T);
 33: }

In this last version I don't pick a random task and wait for it but I rather pick a random completed task, i.e. given the same random number the order in which tasks complete will affect which task is returned.