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有点浪费。 asyncawait都没有给你带来任何好处。 我为什么这么说? 好吧,让我们快速回顾一下await的通常好处。

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

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

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

这样做仍然会使函数返回并表现为异步。 请记住, asyncawait实际上并不是使函数异步执行的原因。 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,则编译器将生成状态机。

第二种方法:您正在返回“热门任务” – 已完成的任务。 此方法将像普通方法一样运行。

顺便说一下,第二种方案缓存这些任务是个好主意。 例如,您可以创建字典巫婆并返回缓存的任务。 如果这样做,则不会每次在堆上分配新任务。