C# 如何从自定义TaskScheduler回退到默认TaskScheduler

C# 如何从自定义TaskScheduler回退到默认TaskScheduler,c#,.net,task-parallel-library,C#,.net,Task Parallel Library,假设我想创建一个自定义TaskScheduler,但在它内部,如果某些条件不适用,则返回默认值。我该怎么做 例如 受保护的覆盖无效队列任务(任务任务){ 如果(/*某些条件*/){ /*手动安排任务,无所谓*/ } /*默认情况下的队列任务--如何*/ } 受保护的重写IEnumerable GetScheduledTasks(){ 返回Enumerable.Concat(/*我的任务*/,/*默认任务--如何?*/); } 我认为你不能(或不应该)这样做,即使你求助于反射黑客。理论上,您需要从

假设我想创建一个自定义TaskScheduler,但在它内部,如果某些条件不适用,则返回默认值。我该怎么做

例如

受保护的覆盖无效队列任务(任务任务){
如果(/*某些条件*/){
/*手动安排任务,无所谓*/
}
/*默认情况下的队列任务--如何*/
}
受保护的重写IEnumerable GetScheduledTasks(){
返回Enumerable.Concat(/*我的任务*/,/*默认任务--如何?*/);
}
我认为你不能(或不应该)这样做,即使你求助于反射黑客。理论上,您需要从现有的非抽象任务调度器派生自定义的
TaskScheduler
,例如

但是,您不能这样做,因为TPL中的任务调度器是
私有的
内部的

在使用
TaskScheduler.QueueTask
的情况下,可能很容易将调用转发到:

然而,你也不能这样做。内部调用
TaskScheduler.QueueTask
,这将导致无限递归

此外,
Task
对象在
Task.Start
中存储对任务调度器的引用。因此,假设您使用反射调用
ThreadPoolTaskScheduler.QueueTask
,它将中断任务与其任务调度器之间的连接


因此,
QueueTask
GetScheduledTasks
TaskScheduler
的一些其他方法被声明为受保护的
。如果你想实现一个自定义任务调度程序,你必须提供完整的实现。

我明白你为什么说我不能这样做,但你为什么认为我不应该这样做?@AndreyShchekin,出于这个原因:
任务
对象在
任务.启动
中存储了对任务调度程序的引用。如果使用自定义任务计划程序启动任务(通过
task.start
task.Factory.StartNew
),将存储对任务计划程序的引用。然后在您的
QueueTask
中调用
defaultTaskScheduler.QueueTask
,任务将在不同的任务调度器上运行,而不是保留引用。这样做的结果可能是不可预测的。我认为它与任何普通的装饰程序没有什么不同——对于外部世界来说,任务实际上是在我的调度程序上运行的,只是它的内部实现使用了另一个调度程序来帮助这一点。另一方面,我认为ThreadPoolScheduler在从另一个调度器传递任务时抛出。无论如何,整个API在可扩展性方面似乎设计得非常糟糕。谢谢你的回答——我同意这个问题没有好的解决方案。
protected override void QueueTask(Task task) {
   if (/* some condition */) {
       /* schedule task manually, does not matter */
   }

   /* queue task on default -- how? */
}

protected override IEnumerable<Task> GetScheduledTasks() {
    return Enumerable.Concat(/* my tasks */, /* tasks from default -- how? */);
}
protected override void QueueTask(Task task) {
   if (/* some condition */) {
       /* schedule task manually, does not matter */
   }

   /* queue task on default -- how? */
   task.Start(TaskScheduler.Default);
}