如何获取使用SynchronizationContext的任务? 那么SynchronizationContext是如何使用的呢?

我还在学习整个任务概念和TPL。 根据我目前的理解, await使用SynchronizationContext函数(如果存在)来“调用”任务“某处”。 另一方面, Task类中的函数不使用上下文,对吧?

因此,例如, Task.Run(...)将始终在线程池的工作线程上调度操作,并完全忽略SynchronizationContext.Currentawait Foobar()会在await之后使用上下文来执行生成的任务吗?

如果这是真的,我的问题是:我如何获得一个实际运行动作但使用SynchronizationContext.Current.Send/Post调度的Task

任何人都可以推荐对SynchronizationContext一个很好的介绍,特别是在框架的其余部分何时以及如何使用它们的时候? MSDN似乎对这堂课非常安静。 顶级Google点击( 此处和此处 )似乎仅适用于Windows Forms调度。 Stephen Cleary撰写了一篇文章 ,很好地了解了已经存在的背景以及它们是如何工作的,但是我不了解实际使用它们的位置和时间。

如何获取实际运行操作但使用SynchronizationContext.Current.Send / Post调度的任务?

使用特殊任务调度程序:

 Task.Factory.StartNew( () => {}, // this will use current synchronization context CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); 

任何人都可以推荐一个很好的SynchronizationContext介绍

请看Stephen Cleary所着的关于SynchronizationContext的文章。

在您了解这一点时,重要的是要指出TPL 使用的 Task 与async / await使用的 Task完全不同,即使它们是相同的类型。 例如,TPL通常使用父/子任务,但async / await不使用。

TPL使用任务调度程序来执行其任务。 正如Dennis所指出的, TaskScheduler.FromCurrentSynchronizationContext将为您提供一个任务调度程序,它使用当前SynchronizationContext上的Post来执行其任务。

async / await通常不使用任务调度程序。 我在我的博客上有一个介绍性的async / awaitpost ,其中包含上下文信息,我在MSDN文章中也简要提到过(虽然很容易忽略)。 本质上,当async方法在await挂起时,默认情况下它将捕获当前的SynchronizationContext (除非它为null ,在这种情况下它将捕获当前的TaskScheduler )。 当async方法恢复时,它将继续在该上下文中执行。

Dennis指出了将任务安排到当前SynchronizationContext的TPL方式,但是在async / await世界中,这种方法不是必需的。 相反,您可以通过Task.Run显式地将任务计划到线程池:

 async Task MyMethodAsync() { // Whee, on a SynchronizationContext here! await Task.Run(() => { }); // Ooo, on the thread pool! // Back on the SynchronizationContext ... // ... automagically! } 

我正好写了我的SynchronizationContext文章,因为MSDN文档非常缺乏。 我在我的博客上有更多的信息 ,但所有重要的部分都在MSDN文章中。 许多类型直接使用AsyncOperation而不是SynchronizationContext ; 最好的文档隐藏在EAP文档(“线程和上下文”部分)下 。 但我还应该指出,由于async / await ,EAP实际上已经过时了,所以我不会使用AsyncOperation (或SynchronizationContext )编写代码 – 除非我实际编写自己的 SynchronizationContext