Proper use of Task.WhenAll

async-await, c#

Solution

The problem with your current code is that you won't be able to handle individual exceptions, if more than one task throws.

If this is a concern, then with the following approach, you can handle them:

public async Task<Task<string>[]> DoIt()
{
    var urls = new string[] { "http://www.msn.com", "http://www.google.com" };

    var tasks = urls.Select(x => this.GetUrlContents(x)).ToArray();

    await Task.WhenAll(tasks);

    return tasks;
}

// ...

static void Main(string[] args)
{
    var lib = new AsyncLib();
    foreach(var item in lib.DoIt().Result)
    {
        Console.WriteLine(item.Result.Length);
    }
    Console.Read();

}

Note I use `ToArray()` to avoid evaluating the enumerable and starting the tasks for more than once (as LINQ is lazy-evaluated).

Updated, now you can further optimize `DoIt` by eliminating `async/await`:

public Task<Task<string>[]> DoIt()
{
    var urls = new string[] { "http://www.msn.com", "http://www.google.com" };

    var tasks = urls.Select(x => this.GetUrlContents(x)).ToArray();

    return Task.Factory.ContinueWhenAll(
        tasks, 
        _ => tasks, 
        CancellationToken.None, 
        TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
}

However, if you do so, be aware of the change in the exception propagation behavior.

Problem

I am trying to wrap my head around `async`/`await` and wanted to know if this is the proper use of the `Task.WhenAll` method: ``` public class AsyncLib { public async Task<IEnumerable<string>> DoIt() { var urls = new string[] { "http://www.msn.com", "http://www.google.com" }; var tasks = urls.Select(x => this.GetUrlContents(x)); var results = await Task.WhenAll(tasks); return results.Select(x => x); } public async Task<string> GetUrlContents(string url) { using (var client = new WebClient()) { return await client.DownloadStringTaskAsync(url); } } } ``` Main This is the calling console application. ``` class Program { static void Main(string[] args) { var lib = new AsyncLib(); foreach(var item in lib.DoIt().Result) { Console.WriteLine(item.Length); } Console.Read(); } } ```

Original source

Related problems