Convert a dictionary of tasks into a dictionary of results

Why didn't the await keyword work in my first example?

The await keyword unwraps the Task<T> within the context of an async method, operates on the underlying result of type <T>, and wraps the async method's return value back in a Task. That is why every async method/function returns one of void, Task, or Task<T> (note that void is only appropriate for events). An async method does not return an unwrapped value; we never see a method signature like public async int SomeMethod(), because returning int would not compile in an async method. It would need to return a Task<int> instead.

What is the right way to do this?

Here is one approach (with a Fiddle) to converting a dictionary with values of type Task<T> to a dictionary with values of type <T>:

using System.Threading.Tasks; 
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public async static void Main()
    {
        // create a dictionary of 10 tasks
        var tasks = Enumerable.Range(0, 10)
            .ToDictionary(i => i, i => Task.FromResult(i * i));

        // await all their results
        // mapping to a collection of KeyValuePairs
        var pairs = await Task.WhenAll(
            tasks.Select(
                async pair => 
                    new KeyValuePair<int, int>(pair.Key, await pair.Value)));

        var dictionary = pairs.ToDictionary(p => p.Key);

        System.Console.WriteLine(dictionary[2].Value); // 4
    }
}