await前后的线程
我们都知道 await 会让当前线程释放回线程池,然后 await后再申请,在默认情况下一放 一申请 这两未必是同一个线程了。
但是我们在写WPF/winform时,如果如下
private async void Button_Click(object sender, RoutedEventArgs e)
{
// UI 线程
myButton.Content = "开始";
await Task.Delay(1000); // 这里会挂起,线程可能切换
// 恢复回来时依然是 UI 线程(默认行为)
myButton.Content = "完成";
}
会发现,后面的UI操作 myButton.Content = 依然可以正常 ,他依然前后是在同一个UI线程中。
这里不得不记录一下了
在 C# 的 async/await 机制里
- await 之前的代码运行在哪个线程,取决于你是在哪个上下文调用的(比如 WPF 中就是 UI 线程)
- await 的时候,当前方法会“挂起”,然后把控制权返回给调用者。
- await 之后继续执行时,是否还在原线程,取决于 SynchronizationContext(同步上下文)。
总结
-
在 WPF 中,默认 await 之后 还是 UI 线程,可以继续安全操作 UI。
-
如果用了 ConfigureAwait(false),就会放弃回 UI 线程,那时候操作 UI 就会报错。
👉 所以一般 UI 层的代码不要用 ConfigureAwait(false),只在底层库里用。
WPF 的情况
在 WPF / WinForms 这样的 UI 框架里,它们有自己的 SynchronizationContext,默认行为是:
- await 之后会自动回到原来的 UI 线程(除非你特意禁用)。
- 所以在 WPF 里,绝大多数情况下你在 UI 线程里 await 之后,继续的代码依然在 UI 线程,可以安全操作 UI。
所以此时正好学到另外一个知识点
什么时候会不回到 UI 线程?
await SomeTask.ConfigureAwait(false);

浙公网安备 33010602011771号