计划程序实例
本文档介绍了并发运行时中计划程序实例的作用,以及如何使用 concurrency::Scheduler 和 concurrency::CurrentScheduler 类创建和管理计划程序实例。 当你希望将显式计划策略与特定类型的工作负载相关联时,计划程序实例非常有用。 例如,你可以创建一个计划程序实例来以提升的线程优先级运行一些任务,并使用默认计划程序以普通线程优先级运行其他任务。
提示
并发运行时提供了一个默认计划程序,因此无需在应用程序中创建一个。 由于任务计划程序有助于优化应用程序的性能,如果你刚开始接触并发运行时,建议从使用并行模式库 (PPL) 或异步代理库开始。
章节
计划程序和 CurrentScheduler 类
任务计划程序使应用程序能够使用一个或多个计划程序实例来计划工作。 concurrency::Scheduler 类表示计划程序实例,并封装与计划任务相关的功能。
附加到计划程序的线程称为执行上下文(或只是上下文)。 在任何时候都可以有一个计划程序在当前上下文中处于活动状态。 活动计划程序也称为“当前计划程序”。 并发运行时使用 concurrency::CurrentScheduler 类提供对当前计划程序的访问。 一个上下文的当前计划程序可能与另一个上下文的当前计划程序不同。 运行时不提供当前计划程序的进程级表示形式。
通常,CurrentScheduler
类用于处理当前计划程序。 当你需要管理一个不是当前计划程序的计划程序时,Scheduler
类非常有用。
以下各部分介绍了如何创建和管理计划程序实例。 有关演示这些任务的完整示例,请参阅如何:管理计划程序实例。
[返回页首]
创建计划程序实例
创建 Scheduler
对象的方法有三种:
如果不存在计划程序,运行时会在你使用运行时功能(例如并行算法)执行工作时,为你创建默认计划程序。 默认计划程序将成为启动并行工作的上下文的当前计划程序。
concurrency::CurrentScheduler::Create 方法将创建一个使用特定策略的
Scheduler
对象,并将该计划程序与当前上下文相关联。concurrency::Scheduler::Create 方法可创建一个使用特定策略的
Scheduler
对象,但不将其与当前上下文相关联。
允许运行时创建默认计划程序后,所有并发任务就可以共享同一计划程序。 通常,并行模式库 (PPL) 或异步代理库提供的功能可用于执行并行工作。 因此,无需直接使用计划程序来控制其策略或生存期。 当你使用 PPL 或代理库时,运行时会创建默认计划程序(如果它不存在),并使它成为每个上下文的当前计划程序。 当你创建计划程序并将其设置为当前计划程序后,运行时会使用该计划程序来计划任务。 只有当你需要特定的计划策略时,才能创建额外的计划程序实例。 有关与计划程序关联的策略的详细信息,请参阅计划程序策略。
[返回页首]
管理计划程序实例的生存期
运行时使用引用计数机制来控制 Scheduler
对象的生存期。
当你使用 CurrentScheduler::Create
方法或 Scheduler::Create
方法创建 Scheduler
对象时,运行时将该计划程序的初始引用计数值设置为一。 当你调用 concurrency::Scheduler::Attach 方法时,运行时会递增引用计数值。 Scheduler::Attach
方法将 Scheduler
对象与当前上下文相关联。 这将使它成为当前计划程序。 当你调用 CurrentScheduler::Create
方法时,运行时将创建 Scheduler
对象并将其附加到当前上下文(并将引用计数值设置为一)。 你还可以使用 concurrency::Scheduler::Reference 方法来递增 Scheduler
对象的引用计数值。
当你调用 concurrency::CurrentScheduler::Detach 方法以分离当前计划程序,或者调用 concurrency::Scheduler::Release 方法时,运行时会递减引用计数值。 当引用计数值达到零时,运行时会在所有计划任务完成后销毁 Scheduler
对象。 一个正在运行的任务被允许递增当前计划程序的引用计数值。 因此,如果引用计数值达到零,并且有一个任务递增了引用计数值,则在引用计数值再次达到零且所有任务完成之前,运行时不会销毁 Scheduler
对象。
运行时为每个上下文维护一个 Scheduler
对象的内部堆栈。 当你调用 Scheduler::Attach
或 CurrentScheduler::Create
方法时,运行时会将该 Scheduler
对象推送到当前上下文的堆栈中。 这将使它成为当前计划程序。 当你调用 CurrentScheduler::Detach
时,运行时会从堆栈中弹出当前上下文的当前计划程序,并将上一个计划程序设置为当前计划程序。
运行时提供了几种方式来管理计划程序实例的生存期。 下表显示了针对创建计划程序或将计划程序附加到当前上下文的每个方法从当前上下文中释放或分离计划程序的适当方法。
创建或附加方法 | 释放或分离方法 |
---|---|
CurrentScheduler::Create |
CurrentScheduler::Detach |
Scheduler::Create |
Scheduler::Release |
Scheduler::Attach |
CurrentScheduler::Detach |
Scheduler::Reference |
Scheduler::Release |
调用不适当的释放或分离方法会在运行时产生不明确的行为。
当你使用的功能(例如 PPL)导致运行时为你创建默认计划程序时,请不要释放或分离此计划程序。 运行时会管理它所创建的任何计划程序的生存期。
由于在所有任务完成之前,运行时不会销毁 Scheduler
对象,你可以使用 concurrency::Scheduler::RegisterShutdownEvent 方法或 concurrency::CurrentScheduler::RegisterShutdownEvent 方法在 Scheduler
对象被销毁时收到通知。 在你必须等待 Scheduler
对象计划的每个任务完成的情况下,这非常有用。
[返回页首]
方法和功能
本部分总结了 CurrentScheduler
和 Scheduler
类的重要方法。
将 CurrentScheduler
类视为创建计划程序以用于当前上下文的帮助程序。 Scheduler
类可以让你控制属于另一个上下文的计划程序。
下表显示了 CurrentScheduler
类定义的重要方法。
方法 | 说明 |
---|---|
创建 | 创建一个使用指定策略的 Scheduler 对象,并将它与当前上下文相关联。 |
Get | 检索指向与当前上下文关联的 Scheduler 对象的指针。 此方法不会递增 Scheduler 对象的引用计数值。 |
分离 | 将当前计划程序与当前上下文分离,并将上一个计划程序设置为当前计划程序。 |
RegisterShutdownEvent | 注册一个事件,在当前计划程序被销毁时,运行时会设置该事件。 |
CreateScheduleGroup | 在当前计划程序中创建 concurrency::ScheduleGroup 对象。 |
ScheduleTask | 将轻量级任务添加到当前计划程序的计划队列。 |
GetPolicy | 检索与当前计划程序关联的策略的副本。 |
下表显示了 Scheduler
类定义的重要方法。
方法 | 说明 |
---|---|
创建 | 创建可使用指定策略的 Scheduler 对象。 |
附加 | 将 Scheduler 对象与当前上下文相关联。 |
引用 | 递增 Scheduler 对象的引用计数值。 |
版本 | 递减 Scheduler 对象的引用计数值。 |
RegisterShutdownEvent | 注册一个事件,在 Scheduler 对象被销毁时,运行时会设置该事件。 |
CreateScheduleGroup | 在 Scheduler 对象中创建 concurrency::ScheduleGroup 对象。 |
ScheduleTask | 从 Scheduler 对象中计划轻量级任务。 |
GetPolicy | 检索与 Scheduler 对象关联的策略的副本。 |
SetDefaultSchedulerPolicy | 设置运行时在创建默认计划程序时要使用的策略。 |
ResetDefaultSchedulerPolicy | 将默认策略还原到调用 SetDefaultSchedulerPolicy 之前处于活动状态的策略。 如果在此调用后创建了默认计划程序,运行时将使用默认策略设置来创建计划程序。 |
[返回页首]
示例
有关如何创建和管理计划程序实例的基本示例,请参阅如何:管理计划程序实例。