如何获得一个使用SynchronizationContext的任务?以及SynchronizationContext是如
本文关键字:SynchronizationContext 任务 是如 以及 何获得 一个 | 更新日期: 2023-09-27 18:16:55
我还在学习整个Task-concept和TPL。根据我目前的理解,await
使用SynchronizationContext函数(如果存在)来"某处"调度任务。另一方面,Task
类中的函数不使用上下文,对吗?
因此,例如Task.Run(...)
将始终在线程池的工作线程上调度操作,而完全忽略SynchronizationContext.Current
。await Foobar()
将使用上下文在await
之后执行生成的任务?
如果这是真的,我的问题是:我怎么能获得一个Task
,它实际上运行一个动作,但使用SynchronizationContext.Current.Send/Post
调度?
谁能推荐一个关于SynchronizationContext
的好的介绍,特别是框架的其余部分何时以及如何使用它们?MSDN似乎对这个类很沉默。Google最热门的搜索结果(这里和这里)似乎只针对Windows窗体调度。Stephen Cleary写了一篇文章,很好地了解了已经存在的上下文以及它们是如何工作的,但我不了解它们实际使用的地点和时间。
我如何获得一个任务,它实际运行一个操作,但使用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
在学习这一点时,重要的是要指出,TPL使用的Task
与async/await使用的Task
完全不同,尽管它们是相同的类型。例如,TPL通常使用父/子任务,但async
/await
不使用。
TaskScheduler.FromCurrentSynchronizationContext
会给你一个任务调度器,它在当前SynchronizationContext
上使用Post
来执行它的任务。
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
。