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?
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.
See more on this question at Stackoverflow