2

I would like to populate a collection using collection initializer that will call async methods:

public class Diagnostics
{
    public async Task<IEnumerable<DiagnosticsInfo>> Get() => new List<DiagnosticsInfo>
    {            
        await GetDiagnosticsInfo1(),
        await GetDiagnosticsInfo2(),
        await GetDiagnosticsInfo3()
    };
}

The aim is for all the GetDiagnosticsInfoX() methods to execute in parallel. I have a suspicion that the generated code will invoke GetDiagnosticsInfoX() methods synchronously - it will await the first call before invoking the second.

Is my gut feel correct?

If so I assume I would need to await all the tasks like this:

public class Diagnostics
{
    public async Task<IEnumerable<DiagnosticsInfo>> Get()
    {
        var task1 = GetDiagnosticsInfo1();
        var task2 = GetDiagnosticsInfo2();
        var task3 = GetDiagnosticsInfo3();

        await Task.WhenAll(task1, task2, task3);

        return new List<DiagnosticsInfo> {task1.Result, task2.Result, task3.Result};
    }
}
Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126

1 Answers1

2

Is my gut feel correct?

Your gut feeling is right. All collection initializer does is invoke the Add method for the collection. This means your code is translated to:

public async Task<IEnumerable<DiagnosticsInfo>> Get()
{
    var list = new List<DiagnosticsInfo>();         
    list.Add(await GetDiagnosticsInfo1());
    list.Add(await GetDiagnosticsInfo2());
    list.Add(await GetDiagnosticsInfo3());
    return list;
}

Using Task.WhenAll will wait for all async methods to complete. You can then return the array you receive:

public async Task<IEnumerable<DiagnosticsInfo>> Get()
{
    var task1 = GetDiagnosticsInfo1();
    var task2 = GetDiagnosticsInfo2();
    var task3 = GetDiagnosticsInfo3();

    return await Task.WhenAll(task1, task2, task3);
}
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321