【问题标题】:Why would i use async instead of non async method为什么我要使用异步而不是非异步方法
【发布时间】:2019-02-22 11:15:05
【问题描述】:

我不明白,我看到.Net Framework 提供的许多方法都有asyncnon-async 两种变体。

我的问题是,考虑到以下限制,async 方法为我提供了什么优势: - 我不会在同一方法中多次获取Task.Result
- 我没有使用CPU-bound 任务(Task.Run(...)

我在MVC 控制器中,我想处理post 请求:

 [HttPost]
 [Route(..)]
 public async Task DoSomething(MyModel model)
 {  
    var asyncResult=await NETMethodAsync(model); //PostAsync,WriteAsync....
    var nonAsyncResult= NETMethod(model); //Post,Write,....etc..
    return result;
 }

在这种情况下,我将在我的方法中只使用一次result,并且我不会多次要求它(await 只会给我完成的任务结果)有什么区别? 我基本上是在我的MethodAsync 中创建一个StateMachine 是为了什么? 我想我可以更快地完成non-async 的操作。

如果我不将方法委托给单独的 Task(如下所示),我为什么要使用 async 版本? 我之所以问,是因为即使是 MVC Controller 模板,默认情况下也使用 async 版本提供所有 CRUD 操作。

Task tsk=Task.Run(async()=> await MethodAsync() );

P.S 在我的场景中,我错过了什么。使用async(内部旋转状态机)比非异步版本更快吗?

【问题讨论】:

  • 正是当您不想等到磁盘、数据库或远程站点响应的 IO 绑定任务时。 MethodAsync 是否合理无法确定,因为您没有发布代码。
  • 但是await-ing 的行为正在阻塞调用线程(而Result 尚未计算)
  • 不,不是。原始线程已发布,可以处理其他请求。 await 等待已经异步操作并在原始同步上下文中恢复执行。对于 ASP.NET Core 应用程序,async/await 意味着更少的线程可以服务更多的请求。或者,如果您有一个高流量站点,则需要更少的服务器来处理相同的流量
  • 还要注意await Task.Run(...) 根本没有帮助 - 释放原始线程只是为了在 new 线程上继续执行。在这种情况下还不如留在原来的线程中,避免切换。
  • 检查Why your ASP.NET Core application won't scale - Damian Edwards, David Fowler。他们解释了在 ASP.NET Core 应用程序中可能损害可伸缩性的各种因素。

标签: asp.net-mvc asynchronous .net-core task-parallel-library


【解决方案1】:

有什么区别?

可扩展性。具体来说,同步方法会阻塞调用线程,而异步方法不会。

这意味着(对于 ASP.NET 应用程序)同步操作方法会在请求期间阻塞请求线程,而异步操作方法不会阻塞该线程。

这反过来又会产生更大的可扩展性。由于线程池是一种有限的资源(特别是它的线程注入率有限),因此异步代码允许您的应用以更少的线程处理更大的负载。

有关详细信息,请参阅my article on async ASP.NET 中的“同步与异步请求处理”部分;本文的该部分适用于所有服务器技术,包括 ASP.NET Core。您还可以查看this gist,它通过限制线程池增长率来展示可伸缩性差异。我没有将该示例移植到 ASP.NET Core,但应该很简单。

【讨论】:

  • 但是当你说 await something(); somethingElse(); 时,你不能传递给 somethingElse ,所以基本上你的线程 blocks 在那个命令。这不像将something() 放在另一个线程中。
  • @BercoviciAdrian:如果您的异步操作方法执行await something();,则请求线程将返回到线程池。稍后,当something 完成时,另一个 请求线程被占用并继续执行异步操作方法,在该线程上调用somethingElse();
  • 所以每当我在await-ing 时,我将无法传递到下一个instruction,但到达该点的线程基本上已被释放,而另一个线程将返回我的结果并继续它离开的方法(预等待)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多