async / await函数比较
我试图理解async / await,我想知道两种方法是否相同。如果不能解释原因?
public async Task GetClient() { return await _clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefaultAsync(); } public Task GetClient2() { return Task.FromResult(_clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefault()); } public async Task Run() { var result = await GetClient(); var result2 = await GetClient2(); }
让我指出一些与你的function有关的事情:
public async Task GetClient() { return await _clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefaultAsync(); }
这第一个function有点浪费。 async
和await
都没有给你带来任何好处。 我为什么这么说? 好吧,让我们快速回顾一下await
的通常好处。
await
允许您执行的操作是在等待任务完成后继续执行方法的其余部分 。 在你的情况下,没有“方法的剩余部分”,因为return await
是方法的最后一个语句。
为什么这样浪费? 好吧,通过标记您的方法async
您基本上告诉编译器生成所有机器(即状态机),以允许您在每次等待之后在同一方法中恢复执行。
这个机器在你的情况下没用,因为在等待恢复执行之后没有任何东西,所以你最好不要将方法标记为async
而不是return await
只是简单地返回由FirstOrDefaultAsync
生成的任务。
这样做仍然会使函数返回并表现为异步。 请记住, async
和await
实际上并不是使函数异步执行的原因。 async/await
只是帮助设置机器,为方法中的各种等待点提供“书签”,以便在每个等待的任务完成后可以在那里恢复执行。
现在让我们谈谈你的第二个function:
public Task GetClient2() { return Task.FromResult(_clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefault()); }
该function根本不是异步的。 它将执行完全同步,根本不会产生线程。
即使你这样做了:
public async Task GetClient2() { return await Task.FromResult(_clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefault()); }
该function仍将完全同步。 请记住, async/await
都是关于设置机器和书签的,但实际上对代码是同步执行还是异步执行没有任何作用。
那为什么会阻塞? 因为FirstOrDefault()
不返回任务,所以这意味着它必须返回一个Client
对象。 这意味着在完全完成linq
链的执行之前,它不能返回任何内容。 然后,您的Task.FromResult
将获取此值并将其包装在预先完成的任务中。
所以回顾一下:
如果需要在方法中间的某处继续执行,请仅使用async/await
。
例:
public async Task IsIntegerIGetFromRemoteServerPostitiveAsync(){ int result = await GetSomeIntegerAsync(); Console.WriteLine('Resuming execution of the method'); return i>0; }
如果你发现你有一个await并且它是方法的最后一行,那么不要使用async/await
,只需返回任务而不是等待它。 这避免了不必要的开销。
例:
public Task GetUserInformationAsync(string username){ var url = $"http://userinfo.com?username={username}" return GetSomeJsonFromHttpServerAsync(url); //Assuming this returns Task }
它们不相同,当您添加async关键字时,您可以启用以下两个function。
-
标记的异步方法可以使用Await或await来指定挂起点。 await运算符告诉编译器,在等待的异步进程完成之前,异步方法无法继续超过该点。 在此期间,控制返回到异步方法的调用者。
在await表达式中暂停异步方法不构成方法的退出,最后块不运行。
-
标记的异步方法本身可以通过调用它的方法来等待。
你应该在这里阅读async / await文档: https : //msdn.microsoft.com/en-us/library/hh191443.aspx
第一种方法:async关键字为生成状态机提供编译信号。 事件如果您将空void方法标记为async,则编译器将生成状态机。
第二种方法:您正在返回“热门任务” – 已完成的任务。 此方法将像普通方法一样运行。
顺便说一下,第二种方案缓存这些任务是个好主意。 例如,您可以创建字典巫婆并返回缓存的任务。 如果这样做,则不会每次在堆上分配新任务。