如何获取使用SynchronizationContext的Task? SynchronizationContext 到底是如何使用的?

问题描述 投票:0回答:2

我仍在学习整个任务概念和 TPL。根据我目前的理解,

await
使用 SynchronizationContext 函数(如果存在)将任务分派到“某处”。另一方面,
Task
类中的函数不使用上下文,对吧?

因此,例如

Task.Run(...)
将始终在线程池的工作线程上分派操作,并完全忽略
SynchronizationContext.Current
await Foobar()
将使用上下文在
await
?

之后执行生成的任务

如果这是真的,我的问题是:如何获得一个

Task
,它实际上运行一个操作,但使用
SynchronizationContext.Current.Send/Post
调度?

任何人都可以推荐一个关于

SynchronizationContext
的很好的介绍,特别是框架的其余部分何时以及如何使用它们? MSDN 似乎对这门课很安静。 Google 的热门搜索(herehere)似乎仅针对 Windows 窗体调度而定制。 Stephen Cleary 写了一篇文章,很高兴了解已经存在的上下文以及它们如何工作,但我缺乏对它们实际使用的地点和时间的了解。

c# async-await synchronizationcontext
2个回答
52
投票

如何获得一个任务,该任务实际上运行一个操作,但使用 SynchronizationContext.Current.Send/Post?

使用特殊的任务调度程序:

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

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

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


28
投票

在学习这一点时,需要指出的是,TPL

 使用的 
Task 与 async/await
 使用的 
Task 有很大不同,尽管它们是同一类型。例如,TPL 通常使用父/子任务,但
async
/
await
则不使用。

TPL 使用任务调度程序来执行其任务。正如 Dennis 指出的,

TaskScheduler.FromCurrentSynchronizationContext
将为您提供一个任务调度程序,它在当前
Post
上使用
SynchronizationContext
来执行其任务。

async
/
await
通常不使用任务调度程序。我的博客上有一篇介绍性的
async
/
await
帖子
,其中包含上下文信息,我还在我的 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 
.

© www.soinside.com 2019 - 2024. All rights reserved.