async await returning Task<List<T>> instead of List<T> on calling aync method

20,714

Solution 1

Why i need to put await on the calling method if i put await it gives compiler error of course because await should have async as well.

There are a few dependencies the compiler needs in order to understand you're running an async method. The signal is the async modifier on the method declaration. Once you mark it as async, you can use the await keyword. That is why async propagates "all the way" down the call stack, as when you call one async method and need to await its result, you'll need to mark the consuming method with the async modifier.

In order to make your method work, you'll need to do the following:

public async Task GetEmployeesAsync()
{
   List<Employees> result = await TestEmployeesGetAsync();
}

As a side note, be aware that you should not expose async wrappers over sync methods.

Solution 2

You essentially need to wait for the result of the task returned by TestEmployeesGetAsync. You can do that asyncrhonously with await which unwraps the result for you to List<Employee> or you can get the result from the task with the Result property. However that can cause a deadlock so you need to be careful.

With async-await it tends to make its way up the call chain, i.e. awaiting an async method requires you to do that in another async method ( as you have found out), and awaiting that method requires you to be in yet another async method, and so the async methods spread through the code base until you reach an event handler or Main (which cannot be marked async).

This proliferation of async methods is not unusual, and to avoid it, you can wait for the task to complete with Task.Wait and Task.Result but these are blocking method and can cause the aforementioned deadlock. It is also an anti-pattern called sync over async and it defeats the purpose of doing the work asynchronously as you'll end up blocking waiting for it to finish anyway.

As pointed out by @BenVoigt, one exception is when you kick off multiple asynchronous requests and then block waiting for all the tasks to complete with Task.WaitAll.

Share:
20,714
Ehsan Sajjad
Author by

Ehsan Sajjad

Available as Mentor at hack.hands() Some Achievements 5th Top Contributor from Pakistan Top User in asp.net mvc from Pakistan 4th Top User in C# and asp.net from Pakistan 5th Top User in jquery from Pakistan Blog Email : [email protected] #SOreadytohelp

Updated on February 13, 2020

Comments

  • Ehsan Sajjad
    Ehsan Sajjad about 4 years

    I am trying to understand the usage of async await and i studied few blog posts and now i have made a testing code but it is not working the way i am expecting it to work.

    I have a method which returns List:

    private List<Employee> GetEmployees()
    {
    
     IList<Employee> list = new List<Employee>();
     list.Add(new Employee() { Id = 1, Age = 20, Name = "Kavin" });
     list.Add(new Employee() { Id = 2, Age = 30, Name = "Alen" });
     list.Add(new Employee() { Id = 3, Age = 20, Name = "Suresh" });
     list.Add(new Employee() { Id = 4, Age = 30, Name = "Jay" });
     list.Add(new Employee() { Id = 5, Age = 20, Name = "Nanda" });
     list.Add(new Employee() { Id = 5, Age = 20, Name = "Kavin" });
     list.Add(new Employee() { Id = 5, Age = 20, Name = "Kavin" });
     list.Add(new Employee() { Id = 1, Age = 23, Name = "Test" });
    
     return list;
    }
    

    Then i wrote my async method:

    private async Task<List<Employee>> TestEmployeesGetAsync()
    {
    
      var result = await Task.Run(() => GetEmployees());
    
      return result;
    }
    

    When i call this method :

    var Result = TestEmployeesGetAsync();
    

    The visual studio is telling me that it returns Task<List<T>> and it usage is:

    List<Employee> result = await TestEmployeesGetAsync();
    

    Why i need to put await on the calling method if i put await it gives compiler error of course because await should have async as well. Can somebody clear my mind how to call it so that i can get List<T> instead of Task<List<T>>

  • Ben Voigt
    Ben Voigt over 9 years
    It doesn't defeat the purpose completely, since you can still have multiple async actions occurring during the wait. For example, using Task.WaitAll.
  • Eren Ersönmez
    Eren Ersönmez over 9 years
    I would expand on "it tends to make its way up the call chain". If you don't already know what that means, it would be hard to understand that sentence.
  • Ehsan Sajjad
    Ehsan Sajjad over 9 years
    you mean i cannot call it without wrapping it in another method which is async?
  • Yuval Itzchakov
    Yuval Itzchakov over 9 years
    99% of the time, that's the way you should be calling your async code.