我已经阅读了很多关于async-await模式的文章,但我仍然不确定 whether the async methods (the awaited methods) run on the UI thread or not . 我总是以SynchronizationContext类结束"async methods run in the same SynchronizationContext with the callee"这究竟是什么意思?
它是新创建的单独线程(我知道它不是)还是ThreadPool线程?
当我读取SynchronizationContext时,我发现它是某种排队的任务 Actuator ,但这些任务在哪里执行?在ThreadPool上?
如果是,则在ThreadPool上执行异步方法,对吧?
2 回答
标记为
async
的方法在调用它的线程上运行,直到它到达其中的第一个await
关键字 .但有一个例外:如果等待的方法在到达
await
关键字时已经完成运行,则执行只是在不切换线程的情况下继续执行 .在这种情况下,如果在线程A上调用该方法,那么也将从线程A打印1 .
然后你转到下一条指令 . 如果
something
返回的Task
已经完成,则在线程A上继续执行 . 如果something
返回的Task
仍在运行,则可以从以下任意一个打印2:线程A再次 - 如果有一个SynchronizationContext强制执行此操作(如在WPF或WinRT应用程序中) . 简单地说,这是通过排队和调度要在线程A上执行的剩余代码(即第三条指令)来完成的 .
在一个完全不同的线程B.
关于你对ThreadPool的疑虑:
正如我们所看到的,
async
方法不能保证在ThreadPool上运行 . 只有一个Task.Run
重载方法安排的工作肯定会在ThreadPool上运行 . 引用Task
MSDN doc:3将由ThreadPool上的一个线程打印 .
如果您还没有,请查看我的async intro post,它解释了
async
和await
的线程行为 .当您调用
async
方法时,它会在第一次await
不完整的操作时同步执行 . 然后async
方法捕获当前的"context"并调度其余部分以便稍后执行,然后返回 .稍后,当操作完成时,
async
方法的其余部分将安排在捕获的"context"上运行 ."context"是当前的
SynchronizationContext
,除非它是null
,在这种情况下它是当前的TaskScheduler
. 当您从UI线程调用async
方法时,您有一个UISynchronizationContext
,它通过将工作发布到UI线程的消息循环来工作 .