同步上下文

时间:2019-03-04 08:24:29

标签: c# async-await

我了解.ConfigureAwait(false)意味着延续不必与输入时在同一线程上。

所以我想知道我将在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

1 个答案:

答案 0 :(得分:3)

SynchronizationContext和执行上下文

每个线程都有与其关联的上下文,这也称为 Current Context ,并且这些上下文可以在线程之间共享。 ExecutionContext包含正在执行程序的当前环境或上下文的相关元数据。

SynchronizationContext代表一种抽象,它定义了应用程序代码的执行位置。 SynchronizationContext表示我们的代码在其中运行的当前环境,它提供了一种将工作单元排队到上下文的方法。 SynchronizationContext具有与其关联的上下文,并且在不同的情况下,不同的框架可能表示不同的事物。例如

  • Winform应用程序– WindowsFormsSynchronizationContext
  • WPF APS – DispatcherSynchronizationContext
  • 默认SynchronizationContext-默认(ThreadPool)SynchronizationContext
  • ASP.Net-AspNetSynchronizationContext

等待如何使用SynchronisationContext的

Async / await 只是编译器的魔力,它使编写异步内容更容易(它不会使您的代码异步运行),它在看到await被拆分时所做的一切将您的方法添加到状态机中,并且当您正在等待的内容完成执行时,状态机将恢复并且您的代码将继续运行。恢复执行称为 continuation

await关键字的一个功能是它在运行异步操作之前捕获了当前的SynchronizationContext,然后它将 continuation 发布到该{{1} },这意味着如果您在SynchronizationContext上处于 UI线程上,则一旦运行完毕,您的代码将继续在 UI线程上执行(即称为卸载

ConfigureAwait()

所有await所做的工作都是配置任务,以使ConfigureAwait(false)之后的 continuation 不必在调用方上下文中运行。这可以带来很多好处,其中之一就是性能提升小,在某些情况下更具争议性地停止死锁。

答案

每次调用await时,它都会创建一个状态机来执行异步等待模式的操作,并设置继续

仅因为您将await设置为ConfigureAwait嵌套在另一个false(状态机)中,并不会更改设置为继续的原始呼叫在调用同步上下文上(如果适用)。

旁注 await正在运行,您应该进行适当的错误检查

更新

  

因此,这意味着我可以在someUIButton_click中做任何我想做的事情,只要它不做   与某些UI组件进行交互

您可以“似乎”自由地从T1someUIButton_click访问 UI组件,除了{strong <在T1中的1}}中,您已经配置了任务,因此继续操作无需返回到调用上下文。在此处访问await组件可能会导致您遇到问题。

T1中的UI之后呢?

在这种情况下,任务(默认情况下)已捕获了当前上下文(可能是您的 UI线程),并且继续将在该上下文上继续。每次嵌套的等待都是不同的情况,调用await(状态机)可以选择继续在哪个上下文上