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

时间:2013-06-04 11:07:25

标签: c# async-await synchronizationcontext

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

因此,例如Task.Run(...)将始终在线程池的工作线程上调度操作,并完全忽略SynchronizationContext.Currentawait Foobar()将使用上下文在await

之后执行生成的任务

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

任何人都可以向SynchronizationContext推荐一个很好的介绍,特别是在框架的其余部分使用它们的时间和方式?关于班级,MSDN似乎非常安静。 Google热门点击(herehere)似乎仅适用于Windows Forms调度。 Stephen Cleary写了an article,这很好地了解了已经存在的情境以及它们是如何工作的,但我不了解它们在何时何地实际使用。

2 个答案:

答案 0 :(得分:39)

  

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

使用特殊任务调度程序:

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

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

请看Stephen Cleary的文章It's All About the SynchronizationContext

答案 1 :(得分:26)

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

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

async / await通常不使用任务计划程序。我在我的博客上有一个介绍async/await post,其中包含了上下文信息,我在MSDN article中也简要提到了它(虽然很容易忽略)。基本上,当async方法在await处暂停时,默认情况下它会捕获当前SynchronizationContext(除非它是null,在这种情况下它会捕获当前TaskScheduler {1}})。当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文档非常缺乏。我有little more information on my blog,但所有重要的位都在MSDN文章中。许多类型直接使用AsyncOperation而不是SynchronizationContext;最好的文档是buried under the EAP docs (section "Threading and Context")。但我还应该指出,由于async / await,EAP实际上已经过时了,所以我不会使用AsyncOperation(或SynchronizationContext)来编写代码 - 除非我是实际上写我自己的 SynchronizationContext