我有一个带有多个Dispatcher
(又名GUI线程,又名消息泵)的应用程序,以确保GUI中运行缓慢、无响应的部分不会严重影响应用程序的其余部分。我也经常使用Task
。
目前,我有一段代码,它有条件地在TaskScheduler
或Dispatcher
上运行Action
,然后直接返回Task
,或者使用TaskCompletionSource
手动创建一个Task
。然而,这种人格分裂的设计使得处理取消,例外等。比我想象的要复杂得多我想在任何地方都使用Task
,而在任何地方都不使用DispatcherOperation
。要做到这一点,我需要调度任务-但如何?
我如何为任何给定的Dispatcher
获取TaskScheduler
?
**编辑:**经过下面的讨论,我决定了以下实现:
public static Task<TaskScheduler> GetScheduler(Dispatcher d) {
var schedulerResult = new TaskCompletionSource<TaskScheduler>();
d.BeginInvoke(() =>
schedulerResult.SetResult(
TaskScheduler.FromCurrentSynchronizationContext()));
return schedulerResult.Task;
}
字符串
6条答案
按热度按时间ttp71kqs1#
步骤1:创建扩展方法:
字符串
步骤2:使用扩展方法:
型
型
xxe27gdn2#
不幸的是,没有内置的方法来做到这一点。没有专门用于将
Dispatcher
Package 在TaskScheduler
中的内置类-我们拥有的最接近的东西是 PackageSynchronizationContext
的类。从SynchronizationContext
构建TaskScheduler
的唯一公共API是Paul Michalik提到的:TaskScheduler.FromCurrentSynchronizationContext
-正如您所观察到的,只有当您已经在相关的同步上下文中(即,在相关的调度程序的线程上)时,它才有效。所以你有三个选择
1.安排好代码,使需要调度器的类在某些时候能够在这些调度器的线程上运行,这样就可以按预期使用
TaskScheduler.FromCurrentSynchronizationContext
。1.使用
Dispatcher.BeginInvoke
在调度器线程上运行一些代码,并在该代码中调用TaskScheduler.FromCurrentSynchronizationContext
。(如果你不能安排1。自然发生,强迫它发生。)1.编写自己的任务调度程序。
uqjltbpv3#
看看
TaskScheduler.FromCurrentSynchronizationContext
。Task框架提供了一种非常灵活的方式来配置计算绑定操作的执行,即使应用程序强加了特定的线程模型。编辑:
嗯,很难从你发布的内容中得到更明确的信息。我知道你正在运行一个多视图应用程序,每个视图都有单独的调度程序,对吗?由于所有的调度都归结为获取
SynchronizationContext
和Post
-ing,因此您可以在您的视图获得TaskScheduler
的某个点获取正确的TaskScheduler
(具有正确SynchronizationContext
的TaskScheduler
)。一种简单的方法是在tak配置期间获取TaskScheduler:字符串
不知道这是否有帮助,如果你正在广泛使用任务,你可能已经知道...
2w2cym1i4#
你可以把整个函数写在一行中:
字符串
而那些满足于默认UI线程的用户可能会发现以下内容足以应付:
型
2eafrhcq5#
这就是我总是如何将async函数调用转换为sync函数调用的方法(对互联网上的某个人来说值得称赞):
字符串
变化:
型
j8yoct9x6#
虽然TaskScheduler中没有专门用于 Package Dispatcher的内置类,但允许您自己编写一个。执行此任务的示例实现如下所示:
字符串