异步等待在调用异步方法时返回Task <List >而不是List

我试图了解异步等待的用法,我研究了一些博客文章,现在我已经制作了一个测试代码,但它没有按照我期望的方式工作。

我有一个返回List的方法:

private List GetEmployees() { IList list = new List(); 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; } 

然后我写了我的异步方法:

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

当我称这种方法时:

 var Result = TestEmployeesGetAsync(); 

visual studio告诉我它返回Task<List> ,它的用法是:

 List result = await TestEmployeesGetAsync(); 

为什么我需要等待调用方法如果我await它当然会给编译器错误,因为await应该具有异步。 有人可以清楚我是如何调用它以便我可以获得List而不是Task<List>

为什么我需要等待调用方法如果我等待它当然会给编译器错误,因为await也应该具有异步。

编译器需要一些依赖项才能理解您正在运行异步方法。 信号是方法声明中的async修饰符。 将其标记为async ,可以使用await关键字。 这就是为什么异步在调用堆栈中“一直”传播的原因,就像调用一个异步方法并需要等待其结果一样,您需要使用async修饰符标记使用方法。

为了使您的方法有效,您需要执行以下操作:

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

作为旁注,请注意不要在同步方法上公开异步包装

您基本上需要等待TestEmployeesGetAsync返回的任务的结果。 您可以使用await异步执行此操作,然后将结果解包为List或者您可以使用Result属性从任务中获取Result 。 但是,这可能会导致死锁,因此您需要小心。

使用async-await它往往会在调用链中上升,即等待async方法需要您在另一个async方法中执行此操作(如您async ),并等待该方法要求您使用另一个async方法,所以async方法通过代码库传播,直到到达事件处理程序或Main (不能标记为async )。

async方法的增加并不罕见,为了避免它,您可以等待Task.WaitTask.Result完成任务,但这些是阻塞方法并且可能导致上述死锁。 它也是一种称为同步异步的反模式,它失败了异步执行工作的目的,因为你最终会阻止等待它完成。

正如@BenVoigt所指出的,一个例外是当您启动多个异步请求然后阻止等待所有任务完成Task.WaitAll