【发布时间】:2019-10-26 19:45:30
【问题描述】:
与本题相关:Does await completely blocks the thread?
[...] 它将首先检查被调用的方法是否完成,如果没有完成,将注册延续并从该方法调用返回。稍后,一旦该方法完成,它将重新进入状态机以完成该方法
还有这个问题:When is the best place to use Task.Result instead of awaiting Task
await 仅表示“在此任务完成之前,此工作流程无法继续进行,因此如果未完成,找到更多工作要做,稍后再回来”
最后是这篇文章:https://blog.stephencleary.com/2012/02/async-and-await.html
如果“await”看到可等待对象尚未完成,则它会异步执行。它告诉 awaitable 在完成时运行该方法的其余部分,然后从 async 方法返回。 稍后,当 awaitable 完成时,它将执行 async 方法的剩余部分。如果您正在等待内置的可等待对象(例如任务),则异步方法的其余部分将在“等待”返回之前捕获的“上下文”上执行。。 em>
因此,从这些帖子中,我了解到 await 运算符确实没有阻塞,但是当我尝试对其进行测试时,我就是无法让这个原理按照它所说的方式工作。显然我错过了一些东西:
//This will take 10 seconds
[HttpGet("test1")]
public async Task<TimeSpan> test()
{
var t1 = DateTime.Now;
var wait1 = DoAsyncEcho("The first!", 10000);
var wait2 = DoAsyncEcho("The second!", 10000);
_logger.LogInformation(await wait1);
_logger.LogInformation(await wait2);
_logger.LogInformation("DONE!");
var t2 = DateTime.Now;
return t2 - t1;
}
//This will take 10 seconds too
[HttpGet("test2")]
public async Task<TimeSpan> test2()
{
var t1 = DateTime.Now;
var wait1 = DoAsyncEcho("The first!", 10000);
var wait2 = DoAsyncEcho("The second!", 10000);
Thread.Sleep(10000);
_logger.LogInformation(await wait1);
_logger.LogInformation(await wait2);
_logger.LogInformation("DONE!");
var t2 = DateTime.Now;
return t2 - t1;
}
//This will take 20
[HttpGet("test3")]
public async Task<TimeSpan> test3()
{
var t1 = DateTime.Now;
var wait1 = await DoAsyncEcho("The first!", 10000);
var wait2 = await DoAsyncEcho("The second!", 10000);
_logger.LogInformation(wait1);
_logger.LogInformation(wait2);
_logger.LogInformation("DONE!");
var t2 = DateTime.Now;
return t2 - t1;
}
//This will take 30
[HttpGet("test4")]
public async Task<TimeSpan> test4()
{
var t1 = DateTime.Now;
var wait1 = await DoAsyncEcho("The first!", 10000);
var wait2 = await DoAsyncEcho("The second!", 10000);
Thread.Sleep(10000);
_logger.LogInformation(wait1);
_logger.LogInformation(wait2);
_logger.LogInformation("DONE!");
var t2 = DateTime.Now;
return t2 - t1;
}
private Task<string> DoAsyncEcho(string v, int t)
{
return Task<string>.Factory.StartNew(() =>
{
Thread.Sleep(t);
return v;
}
);
}
正如我从 test3 和 test4 方法中看到的,await 确实在等待,它不会进入状态机并稍后进行回调,因为它等待第一个 @ 的整整 10 秒987654328@,然后在第二次通话中再打 10 秒。在 test1 和 test2 方法上,执行时间持续 10 秒,因为代码不会等待 DoAsyncEcho 的返回,而是稍后等待结果。特别是 test2 方法并行休眠 10 秒的 3 次调用,所以毕竟它只是一个 10 秒的运行。
我在这里缺少什么?
【问题讨论】:
-
What do I'm missing here?你期望什么结果('nt)?为什么?你的时间安排在我看来是合理的。 -
由于发布的问题和我期待等待不等待的文章,是直接写在异步调用上还是稍后在使用值时写。我希望它进入所谓的状态机,它会记住调用的状态,并且仅在绝对需要等待结果值时才等待它们。 tl;博士;让所有方法运行相同的时间
-
await X();将等待任务完成,然后继续执行下一条语句。这就是你所看到的。 -
它异步等待,它不会阻塞线程。
-
在第一次测试中,您几乎同时开始任务,因此它们也几乎同时完成(大约 10 秒)。在 test2 中它是一样的,但是你睡了 10 秒(在任务完成之前)。在此睡眠时间之后,任务将完成,这就是为什么时间也在 10 秒左右。在 test3 中,您等到第一个任务完成,然后等到 2d 任务完成,这就是为什么它是 20 秒。在 test4 中,睡眠时间相同加 10 秒
标签: c# asynchronous async-await