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