【发布时间】:2018-11-28 00:01:16
【问题描述】:
只调用一个内衬异步等待方法的异步等待方法有什么用?它们跨越多少个线程?您最终可以消耗多少 CPU? 嗨,最近我看到很多方法使用 async 和 await 关键字。我仍然无法理解它们的使用和潜在的行为以及它们在如下应用时的优势。当他们将 CPU 用于所有事情时,我也观察到了 CPU 的问题(达到 100%),并且在某些情况下,我发现 thread.run 是 CPU 利用率的罪魁祸首。
myController.cs
[HttpPost]
[ProducesResponseType(body)]
public async Task<IActionResult> Post([FromBody]Body body){
_MyClassService.sendMessage(body);
return Ok(body);
}
我的服务类
Myclass.cs
private async void sendMessage(){
await SendToProperChannel();
}
private async Task SendToProperChannel(){
await DoWorkInProperChannel();
}
private Task<int> DoWorkInProperChannel(){
await SomethingThatTakes5Seconds();
return 1+1;
}
据我所知。
我们使控制器请求异步,以便不阻塞主线程,从而允许在控制器级别接收更高的吞吐量。
我们还将所有函数设为异步,以免阻塞调用这些方法的上层线程。
我也明白,由于我们有这么多的等待,每个人都会返回一个任务,但也有一个线程正在处理等待完成的工作。
我仍然不清楚线程号,但我相信我们会产生超过 1 个线程来满足单个请求。
我的问题。
如果上面的方法没有响应就无法继续,那么让一个衬垫等待有什么用?实际上,API 可以接收更多的吞吐量,但是从那里开始一切都会同步,而且产生更多线程只是为了在我的类中的方法之间跳转似乎并不健康。
如果我只在一个班轮上等待,在这个特定的代码中,结果与删除等待不一样吗?
所有方法也将处理更多吞吐量,因为它们不会阻塞,但也会产生更多线程?
启动异步方法并在同一方法中等待响应的语法是怎样的。
例子:
private async Task<int> myAsyncWorkerMethod(){
var myNeededValue=methodThatINeed();
var mySecondValue=methodWithSecondValue();
await myNeededValue;
await mySecondValue;
return myNeededValue+mySecondValue;
}
与只处理所有下游调用的线程池相比,异步和等待有什么好处,您可以轻松控制其大小并轻松检测线程饥饿和队列深度? (我可能在这里使用了一些可能不适用的 java 术语)
想法
在其他语言中,我已经看到线程上下文更改的影响,如果您的 CPU 不够强大或由于线程池大小而导致线程饥饿,那么这个 .net 不受控制的线程池是否不会产生相同的影响,只是随心所欲地使用 CPU?
如果您需要异步调用返回等待语句的响应,则无需创建异步调用。只有当你需要对上述方法做一些工作时才需要异步?
即使你正在等待另一个类的方法结果,除非你不想阻塞主线程,你也不应该等待它。
提前致谢
【问题讨论】:
-
没有
Thread.sleep但Thread.Sleep返回 void ... 所以它不能像await Thread.Sleep(..)那样使用 -
是的,你应该等待
Task.Delay,而不是Thread.Sleep。Thread.Sleep言行一致 - 它使线程休眠 N 毫秒,在这段时间内浪费了该线程(这与await的好处相反 -
编辑后...问题出在
SomethingThatTakes5Seconds
标签: c# .net multithreading asynchronous async-await