我理解.ConfigureAwait(false)
意味着continuation不一定要在进入时所在的同一线程上。
所以我想知道在someUIButton_click中我会得到什么样的同步上下文。
static async void someUIButton_click()
{
await T1();
// Am I sur to be on the UI thread ?
}
static async Task T1() => await doSomethingAsync().ConfigureAwait(false)
上下文: C#、winforms、.Net 4.7
发布于 2019-03-04 16:29:04
SynchronizationContext和执行上下文
每个线程都有一个与之关联的上下文,这也称为当前上下文,这些上下文可以在线程之间共享。ExecutionContext
包含程序在其中执行的当前环境或上下文的相关元数据。
SynchronizationContext
表示一个抽象,它定义了执行应用程序代码的位置。SynchronizationContext
是代码运行的当前环境的表示,它提供了一种将工作单元排队到上下文的方法。SynchronizationContext
有一个与之相关的上下文,在不同的情况下,不同的框架可能代表不同的东西。例如
默认DispatcherSynchronizationContext
WindowsFormsSynchronizationContext
AspNetSynchronizationContext
SynchronizationContext
await如何使用SynchronisationContext的
Async/await只是一个编译器魔术,它使编写异步东西变得更容易(它不会让你的代码异步运行),当它看到一个await
时,它所做的就是将你的方法拆分到一个状态机中,当你等待的东西完成执行时,状态机被恢复,你的代码继续运行。恢复执行称为延续。
await
关键字的一个特性是,它在运行异步操作之前捕获当前的SynchronizationContext
,然后它将继续发送到该SynchronizationContext
,这意味着如果您在卸载时正在UI线程上,一旦它完成运行,您的代码将继续在UI线程上执行(这称为await
)。
ConfigureAwait()
所有ConfigureAwait(false)
所做的就是配置任务,这样await
之后的context就不必在调用者上下文中运行了。这可能有几个好处,其中之一是小的性能增益,更有争议的是在某些情况下阻止死锁。
答案
每次调用await
时,它都会创建一个状态机来实现异步等待模式的奇迹,并设置一个延续。
仅仅因为您将ConfigureAwait
设置为false
嵌套在另一个await
(状态机)中并不会改变原始调用,该调用被设置为在调用同步上下文(如果适用)上继续执行。
旁注: someUIButton_click
在运行时未被观察到,您应该进行适当的错误检查
更新
,这意味着我可以在
T1
中做任何我想做的事情,只要它不与某些UI组件交互
但是,您“看似”可以自由地从someUIButton_click
和T1
访问UI组件,例外情况是,在T1
中的 await
之后,您已经配置了任务,以便configured不需要返回到调用上下文。在这里访问UI
组件可能会给您带来问题。
那么在someUIButton_click
中的await
之后会怎样呢
在这种情况下,任务(默认情况下)捕获了当前上下文(假设是您的UI线程),并且将在该上下文上继续执行。每个嵌套的等待都是一种不同的情况,调用await
(状态机)可以选择它继续运行的上下文
https://stackoverflow.com/questions/54979220
复制相似问题