Combining tasks results in a dictionary

I'm trying to parallelize work that relies on external resources, and combine it into a single resulting dictionary.

To illustrate my need, imagine I want to download a set of file, and put each result in a dictionary, where the key is the url:

string[] urls = { "http://msdn.microsoft.com", "http://www.stackoverflow.com", "http://www.google.com" };

var fileContentTask = GetUrls(urls);

fileContentTask.Wait();

Dictionary<string, string> result = fileContentTask.Result;
// Do something

However, I was able to code the GetUrls methode. I can generate all the tasks, but I didn't found how to consolidate the result in the dictionary:

static Task<Dictionary<string,string>> GetUrls(string[] urls)
{
    var subTasks = from url in urls
                   let wc = new WebClient()
                   select wc.DownloadStringTaskAsync(url);

    return Task.WhenAll(subTasks); // Does not compile
}

How can I merge the resulting tasks into a dictionary?

Jon Skeet
people
quotationmark

You need to perform the mapping yourself. For example, you could use:

static async Task<Dictionary<string,string>> GetUrls(string[] urls)
{
    var tasks = urls.Select(async url =>
    {
        using (var client = new WebClient())
        {
            return new { url, content = await client.DownloadStringTaskAsync(url) };
        };
    }).ToList();
    var results = await Task.WhenAll(tasks);
    return results.ToDictionary(pair => pair.url, pair => pair.content);
}

Note how the method has to be async so that you can use await within it.

people

See more on this question at Stackoverflow