我有一个具有多个Dispatcher
(又名 GUI 线程、又名消息泵)的应用程序,以确保 GUI 的缓慢且无响应的部分运行,而不会严重影响应用程序的其余部分。我也经常使用 Task
。
目前,我的代码可以在 TaskScheduler
或 Dispatcher
上有条件地运行 Action
,然后返回 Task
直接或使用 TaskCompletionSource
手动创建一个。然而,这种人格 split 的设计使得处理取消、异常(exception)等事情比我想象的要复杂得多。我想在任何地方使用 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;
}
最佳答案
第 1 步:创建扩展方法:
public static Task<TaskScheduler> ToTaskSchedulerAsync (
this Dispatcher dispatcher,
DispatcherPriority priority = DispatcherPriority.Normal) {
var taskCompletionSource = new TaskCompletionSource<TaskScheduler> ();
var invocation = dispatcher.BeginInvoke (new Action (() =>
taskCompletionSource.SetResult (
TaskScheduler.FromCurrentSynchronizationContext ())), priority);
invocation.Aborted += (s, e) =>
taskCompletionSource.SetCanceled ();
return taskCompletionSource.Task;
}
第2步:使用扩展方法:
旧语法:
var taskSchedulerAsync = Dispatcher.CurrentDispatcher.ToTaskSchedulerAsync ();
var taskFactoryAsync = taskSchedulerAsync.ContinueWith<TaskFactory> (_ =>
new TaskFactory (taskSchedulerAsync.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
// this is the only blocking statement, not needed once we have await
var taskFactory = taskFactoryAsync.Result;
var task = taskFactory.StartNew (() => { ... });
新语法:
var taskScheduler = await Dispatcher.CurrentDispatcher.ToTaskSchedulerAsync ();
var taskFactory = new TaskFactory (taskScheduler);
var task = taskFactory.StartNew (() => { ... });
关于.net - 如何获取调度程序的 TaskScheduler?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6368885/