async / await函数比较

时间:2015-08-31 22:12:58

标签: c# async-await

我正在尝试理解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> 
   "(" ")" ";"
}

3 个答案:

答案 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();
}

这第一个功能有点浪费。 asyncawait都没有给您带来任何好处。我为什么这么说?好吧,让我们快速回顾await的常见好处。

await允许您执行的操作是在等待任务完成后继续执行方法的其余部分。在您的情况下,没有“方法的其余部分”,因为return await是方法的最后一个语句。

为什么这会浪费?好吧,通过标记方法async,您基本上告诉编译器生成所有机器(即状态机),以允许您在每次等待之后在同一方法中恢复执行。

这个机器在你的情况下是无用的,因为在等待恢复执行之后没有任何东西,所以你最好标记方法async而不是return await只需简单地返回FirstOrDefaultAsync生成的任务。

执行此操作仍会使函数返回并执行异步操作。请记住,asyncawait实际上并不是使函数异步执行的原因。 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>
}