在阅读了 Stephen Toub 关于 SynchronizationContext 的文章后,我对这段 .NET 4.5 代码的输出提出了一个问题:
private void btnDoSomething_Click()
{
LogSyncContext("btnDoSomething_Click");
DoItAsync().Wait();
}
private async Task DoItAsync()
{
LogSyncContext("DoItAsync");
await PerformServiceCall().ConfigureAwait(false); //to avoid deadlocking
}
private async Task PerformServiceCall()
{
LogSyncContext("PerformServiceCall 1");
HttpResponseMessage message = await new HttpClient
{
BaseAddress = new Uri("http://my-service")
}
.GetAsync("/").ConfigureAwait(false); //to avoid deadlocking
LogSyncContext("PerformServiceCall 2");
await ProcessMessage(message);
LogSyncContext("PerformServiceCall 3");
}
private async Task ProcessMessage(HttpResponseMessage message)
{
LogSyncContext("ProcessMessage");
string data = await message.Content.ReadAsStringAsync();
//do something with data
}
private static void LogSyncContext(string statementId)
{
Trace.WriteLine(String.Format("{0} {1}", statementId, SynchronizationContext.Current != null ? SynchronizationContext.Current.GetType().Name : TaskScheduler.Current.GetType().Name));
}
输出是:
btnDoSomething_Click WindowsFormsSynchronizationContext
DoItAsync WindowsFormsSynchronizationContext
PerformServiceCall 1 WindowsFormsSynchronizationContext
PerformServiceCall 2 线程池任务调度器
ProcessMessage ThreadPoolTaskScheduler
PerformServiceCall 3 线程池任务调度器
但我希望 PerformServiceCall 1 不会出现在 WindowsFormsSynchronizationContext 上,因为文章指出“SynchronizationContext.Current 不会在等待点之间“流动”...
当使用 Task.Run 和异步 lambda 调用 PerformServiceCall 时,上下文不会被传递,如下所示:
await Task.Run(async () =>
{
await PerformServiceCall();
}).ConfigureAwait(false);
任何人都可以澄清或指出一些关于此的文件吗?