Convert Dictionary<string, Task<string>> to Dictionary<string, string>

c#, dictionary, linq, microsoft-metro

Solution

You do not want to throw an Exception in after you started some tasks, better validate first.

    private static async Task<Dictionary<string, string>> GetETagsAsync(List<string> feedsLink)
    {
        ValidateFeedsLinkFormat(feedsLink);

        var _eTags = feedsLink.ToDictionary(f => f, f => GetETagAsync(f));
        await TaskEx.WhenAll(_eTags.Values);

        var eTags = _eTags.ToDictionary(k => k.Key, k => k.Value.Result);

        return eTags;
    }

This code starts all the tasks, as yours did, but with a single await for all the links. You do not want to use an instance of Stopwatch on multiple threads : from MSDN: "Any instance members are not guaranteed to be thread safe." You can use `Stopwatch.GetTimestamp();` twice and compare the results.

Problem

I don't want to use a `foreach` loop twice, so I tried to use LINQ, but unfortunately this doesn't work: ``` return _etags.ToDictionary(item => item.Key, async item => await item.Value); ``` Can anyone tell me what should I do to improve my code, or how can I convert `Dictionary<string, Task<string>>` to `Dictionary<string, string>`? Here is my code: ``` private static async Task<Dictionary<string, string>> GetETagsAsync(List<string> feedsLink) { var eTags = new Dictionary<string, string>(feedsLink.Count); System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); var _eTags = new Dictionary<string, Task<string>>(feedsLink.Count); eTags = new Dictionary<string, string>(feedsLink.Count); foreach (string feedLink in feedsLink) { if (Uri.IsWellFormedUriString(feedLink, UriKind.Absolute)) { _eTags.Add(feedLink, GetETagAsync(feedLink)); } else { throw new FormatException(); } } foreach (KeyValuePair<string, Task<string>> eTag in _eTags) { eTags.Add(eTag.Key, await eTag.Value); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; return eTags; } ```

Original source