Let*_*man 5 c# asynchronous async-await
我知道有很多关于async/await的问题,但我找不到任何答案.
我遇到了一些我不理解的东西,请考虑以下代码:
void Main()
{
Poetry();
while (true)
{
Console.WriteLine("Outside, within Main.");
Thread.Sleep(200);
}
}
async void Poetry()
{
//.. stuff happens before await
await Task.Delay(10);
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Inside, after await.");
Thread.Sleep(200);
}
}
Run Code Online (Sandbox Code Playgroud)
显然,在await运算符上,控件返回给调用者,而正在等待的方法正在后台运行.(假设IO操作)
但是在控制返回到await运算符之后,执行变为并行,而不是(我的期望)保持单线程.
我希望在"延迟"完成之后,线程将被强制回到Poetry方法,从它离开的地方继续.
它做的.对我来说奇怪的是,为什么"Main"方法一直在运行?是一个线程从一个跳到另一个?还是有两个平行的线程?
这不是一个线程安全问题吗?
我发现这令人困惑.我不是专家.谢谢.
我在博客上有关于async方法如何恢复的说明await.本质上,await捕获电流SynchronizationContext除非它null在哪种情况下捕获电流TaskScheduler.然后使用该"上下文"来安排该方法的其余部分.
由于您正在执行控制台应用程序,因此没有SynchronizationContext,并且TaskScheduler捕获默认值以执行该async方法的其余部分.该上下文将该async方法排队到线程池.除非你实际上给它一个带有SynchronizationContext(或TaskScheduler)队列到主循环的主循环,否则无法返回到Console应用程序的主线程.
我想在这里回答我自己的问题。
你们中的一些人给了我很好的答案,这些都帮助我更好地理解(并得到了点赞)。可能没有人给我完整的答案,因为我没有提出完整的问题。无论如何,有人会遇到我的确切误解,我希望这是第一个答案(但我建议查看下面的更多答案)。
因此,Task.Delay 使用Timer操作系统在 N 毫秒后触发事件。在此期间之后,将创建一个新的池线程,它基本上几乎不执行任何操作。
wait 关键字意味着线程完成后(并且它几乎不执行任何操作),它应该继续执行 wait 关键字之后的任何操作。
正如其他答案中提到的,这是同步上下文。
如果没有这样的上下文,则相同的新创建的池线程将继续运行等待之后发生的事情。
如果存在同步上下文,则新创建的池线程只会将等待之后的任何内容推送到同步上下文中。
为了这个目的,这里有几点我没有意识到的:
不管怎样,我建议阅读C# 5.0 In A Nutshell的“并发与异步”一章。这对我帮助很大。太棒了,实际上解释了整个故事。
| 归档时间: |
|
| 查看次数: |
1074 次 |
| 最近记录: |