我正在尝试了解async await的用法,我研究了一些博客文章,现在我已经制作了一个测试代码,但它的工作方式并不像我期望的那样。
我有一个返回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;
}
然后我写了我的异步方法:
private async Task<List<Employee>> TestEmployeesGetAsync()
{
var result = await Task.Run(() => GetEmployees());
return result;
}
当我称这种方法时:
var Result = TestEmployeesGetAsync();
视觉工作室告诉我它返回Task<List<T>>
,它的用法是:
List<Employee> result = await TestEmployeesGetAsync();
为什么我需要在调用方法上放置等待如果我放await
它当然会给编译错误,因为await
也应该有异步。有人可以清楚我是如何调用它以便我可以List<T>
而不是Task<List<T>>
答案 0 :(得分:7)
为什么我需要等待调用方法,如果我等待它给出 编译错误当然因为await也应该具有异步。
编译器需要有一些依赖项,以便了解您正在运行异步方法。信号是方法声明中的async
修饰符。将其标记为async
后,您可以使用await
关键字。这就是为什么异步在调用堆栈中“一路”传播的原因,就像调用一个异步方法并需要等待其结果一样,你需要使用async修饰符标记使用方法。
为了使您的方法有效,您需要执行以下操作:
public async Task GetEmployeesAsync()
{
List<Employees> result = await TestEmployeesGetAsync();
}
作为旁注,请注意you should not expose async wrappers over sync methods。
答案 1 :(得分:1)
您基本上需要等待TestEmployeesGetAsync
返回的任务的结果。您可以使用await
异步执行该操作,将结果解包到List<Employee>
,或者您可以使用Result
属性从任务中获取结果。但是这可以cause a deadlock,所以你需要小心。
使用async-await
时,它往往会在调用链中上升,即等待async
方法需要您在另一个async
方法中执行此操作(如您所知),并等待该方法要求您使用另一种async
方法,因此async
方法会在代码库中传播,直到您到达事件处理程序或Main
(无法标记{ {1}})。
async
方法的增加并不罕见,为避免它,您可以等待async
和Task.Wait
完成任务,但这些是阻塞方法,可能会导致上述僵局。它也是一种称为同步异步的反模式,它无法异步地完成工作的目的,因为你最终会阻止等待它完成。
正如@BenVoigt所指出的,一个例外是当您启动多个异步请求然后阻止等待所有任务完成Task.Result
时。