C# 同步上下文

如果验证方法中使用的线程,会发现 CallerWithAsync 方法、CallerWithAwaiter 方法和 CallerWithContinuationTask 方法,在方法的不同生命阶段使用了不同的线程。一个线程用于调用 GreetingAsync 方法,另外一个线程执行 await 关键字后面的代码,或者继续执行 ContinueWith 方法内的代码块。

使用一个控制台应用程序,通常不会有什么问题。但是,必须保证在所有应该完成的后台任务完成之前,至少有一个前台线程仍然在运行。示例应用程序调用Console.ReadLine 来保证主线程一直在运行,直到按下返回键。.

为了执行某些动作,有些应用程序会绑定到指定的线程上(例如,在 WPF 或Windows 应用程序中,只有 UI 线程才能访问 UI 元素),这将会是一个问题。

如果使用 async 和 await 关键字,当 await 完成之后,不需要进行任何特别处理,就能访问 UI 线程。默认情况下,生成的代码会把线程转换到拥有同步上下文的线程中。WPF 应用程序设置了 DispatcherSynchronizationContext 属性,Windows Forms 应用程序设置了 WindowsFormsSynchronizationContext属性。Windows 应用程序使用 WinRTSynchronizationContext。如果调用异步方法的线程分配给了同步上下文,await 完成之后将继续执行。默认情况下,使用了同步上下文。如果不使用相同的同步上下文,则必须调用 Task 方法 ConfigureAwait(continueOnCapturedContext:false)。例如,一个 Windows 应用程序,其 await 后面的代码没有用到任何的 UI 元素。在这种情况下,避免切换到同步上下文会执行得更快。