Home > OS >  C# Async Wait - do I need wait?
C# Async Wait - do I need wait?

Time:07-15

I have to retrieve results from two different methods/stored procedures and return combiled results. Is this the most efficient way to use Async Wait or do I need to also wait for both to complete before combining results?

public async Task<IEnumerable<Reports>> GetReports(int days = 0)
{
    List<Reports> data = new List<Reports>();

    List<Reports> AdHocdata = (List<Reports>) await GetAdHocReports(days);
    List<Reports> Pushdata = (List<Reports>) await GetPushReports(days);

    data.AddRange(AdHocdata);
    data.AddRange(Pushdata);

    return data;
}

CodePudding user response:

What you're doing is fine, although it will wait for one report to finish before even starting the second one. If you'd like to run them in parallel, don't await the task until you actually need the data.

public async Task<IEnumerable<Reports>> GetReports(int days = 0)
{
    List<Reports> data = new List<Reports>();

    var x = GetAdHocReports(days);  //Start task, but don't wait
    var y = GetPushReports(days);   //Start task, but don't wait

    data.AddRange(await x);   //Wait for and get the data
    data.AddRange(await y);   //Wait for and get the data

    return data;
}

CodePudding user response:

do I need to also wait for both to complete before combining results?

You already are. Both awaits must complete before the execution reaches the AddRange calls. Note that this also means the awaits run sequentially: the next has not begun until the previous has completed.

If these two reports can be obtained in parallel, then you could use Task.WhenAll to do a single blocking await instead:

public async Task<IEnumerable<Reports>> GetReports(int days = 0)
{
    // The `System.Collections.Concurrent` classes are preferred
    // since you're accessing the object in parallel
    ConcurrentBag<Reports> data = new ConcurrentBag<Reports>();

    await Task.WhenAll(new Task[]
    {
        Task.Run(async () => data.AddRange(await GetAdHocReports(days))),
        Task.Run(async () => data.AddRange(await GetPushReports(days))),
    });

    return data.AsEnumerable();
}
  • Related