C#面试题更新 2026-08-05

请说明在 C# 中如何实现自定义的 TaskScheduler,例如重写哪些方法、如何控制任务排队和执行调度?

编码实现技术原理C#

考察说明

考察对 TaskScheduler 抽象及自定义调度机制的理解。

回答思路

  1. 【回答框架 1】TaskScheduler 是抽象类,负责将 Task 调度到线程池或特定执行环境。自定义时需继承并重写 QueueTask、TryExecuteTaskInline 和 GetScheduledTasks。QueueTask 将任务放入自定义队列,TryExecuteTaskInline 决定内联执行策略,GetScheduledTasks 返回待执行任务快照。
  2. 【回答框架 2】常用实现如基于 Thread 的 LongRunningTaskScheduler 或支持并发上限的 LimitedConcurrencyLevelTaskScheduler。通过重写 MaximumConcurrencyLevel 属性控制并行度,并在 QueueTask 中按需启动线程或使用任务队列配合信号量。
  3. 【回答框架 3】调度时注意线程安全,队列操作需加锁,避免死锁和竞态。同时考虑内联执行:TryExecuteTaskInline 返回 true 表示立即执行,需检查当前线程上下文是否合适。
  4. 【回答框架 4】高级场景可使用派生自 TaskScheduler 的包装类,结合 SynchronizationContext 实现 UI 线程调度,或实现任务优先级、超时取消等策略。
  5. 【回答框架 5】最终需理解 TaskScheduler 与 TaskFactory 的关系,通过 TaskFactory 指定自定义调度器,并注意调度器对任务执行上下文的影响。
  6. 【关键点 1】继承 TaskScheduler 需实现 QueueTask、TryExecuteTaskInline、GetScheduledTasks 三个方法。
  7. 【关键点 2】MaximumConcurrencyLevel 控制最大并发任务数,默认 1 时串行执行。
  8. 【关键点 3】线程安全:队列使用锁或 ConcurrentQueue 确保并发访问安全。
  9. 【关键点 4】内联执行可能导致调用栈递归,需谨慎使用并判断执行上下文。
  10. 【关键点 5】自定义调度器可与 TaskFactory 结合,灵活控制任务执行策略。
  11. 【易错点 1】过度内联执行容易导致栈溢出或破坏调度语义。
  12. 【易错点 2】忽略线程安全可能导致队列 state 损坏。
  13. 【易错点 3】将 MaximumConcurrencyLevel 设为过小可能引发任务饥饿。