上下文
更新:2010 年 7 月
本文档介绍并发运行时中上下文的角色。 附加到计划程序的线程称为“执行上下文”或简称为“上下文”。 Concurrency::wait 函数和 Concurrency::Context 类允许您控制上下文的行为。 使用 wait 函数可在指定的时间段内挂起当前上下文。 当您需要对上下文何时阻止、取消阻止和让出资源,以及何时要超额订阅当前上下文进行更多控制时,可使用 Context 类。
提示
并发运行时提供默认的计划程序,因此您不需要在应用程序中再创建一个计划程序。 由于任务计划程序可帮助您优化应用程序的性能,因此如果您不熟悉并发运行时,则建议您先使用 并行模式库 (PPL) 或 异步代理库。
wait 函数
Concurrency::wait 函数通过协作使当前上下文让出指定毫秒数的执行时间。 运行时使用让出时间来执行其他任务。 指定的时间过去后,运行时重新计划执行上下文。 因此,wait 函数挂起当前上下文的时间可能长于为 milliseconds 参数提供的值。
对 milliseconds 参数传递 0(零)会导致运行时挂起当前上下文,直到为所有其他活动上下文提供了执行工作的机会。 这样,您便可以将一个任务的资源让出给所有其他活动任务。
示例
有关使用 wait 函数让出当前上下文的资源,以便允许其他上下文运行的示例,请参见如何:使用计划组影响执行顺序。
Context 类
Concurrency::Context 类为执行上下文提供编程抽象,另外还提供两个重要功能:以协作方式阻止、取消阻止当前上下文和让出当前上下文资源的功能,以及过度订阅当前上下文的功能。
协作阻止
利用 Context 类,可以阻止或退出当前执行上下文。 在当前上下文由于资源不可用而无法继续时,可使用阻止或让出功能。
Concurrency::Context::Block 方法可阻止当前上下文。 被阻止的上下文让出其处理资源,以便运行时可执行其他任务。 Concurrency::Context::Unblock 方法可取消阻止被阻止的上下文。 必须从调用 Context::Block 的上下文之外的其他上下文调用 Context::Unblock 方法。 如果上下文尝试取消阻止自身,则运行时将引发 Concurrency::context_self_unblock。
若要以协作方式阻止和取消阻止上下文,通常需要调用 Concurrency::Context::CurrentContext 以检索指向与当前线程关联的 Context 对象的指针,并保存结果。 然后调用 Context::Block 方法以阻止当前上下文。 接下来,从另一个上下文调用 Context::Unblock 以取消阻止被阻止的上下文。
每一对调用都必须与 Context::Block 和 Context::Unblock 相匹配。 如果在依次调用 Context::Block 或 Context::Unblock 方法时没有与另一方法的匹配调用,则运行时将引发 Concurrency::context_unblock_unbalanced。 但是,在调用 Context::Unblock 之前不必调用 Context::Block。 例如,如果一个上下文在另一个上下文针对该上下文调用 Context::Block 之前调用 Context::Unblock,则该上下文保持取消阻止。
Concurrency::Context::Yield 方法可让出执行资源,以便运行时可以执行其他任务,然后重新计划执行上下文。 当您调用 Context::Block 方法时,运行时不重新计划上下文。
示例
有关使用 Context::Block、Context::Unblock 和 Context::Yield 方法实现协作信号量类的示例,请参见如何:使用上下文类实现协作信号量。
过度订阅
默认计划程序创建的线程数与可用硬件线程的数量相同。 使用过度订阅可为给定的硬件线程创建附加线程。
对于计算量相当大的操作,过度订阅通常不会带来优势,因为它引入了额外的系统开销。 但是,对于延迟时间很长的任务(例如从磁盘或通过网络连接读取数据),过度订阅可以提高某些应用程序的总体效率。
提示
仅从由并发运行时创建的非 UMS 线程中启用过度订阅。 如果从不是由运行时创建的线程(包括主线程)中调用过度订阅,则过度订阅将不起作用。 此外,如果从使用 UMS 线程计划任务的上下文中调用过度订阅,过度订阅也将不起作用,因为 UMS 线程允许计划程序在出现阻塞操作时使用全部资源。
若要在当前上下文中启用过度订阅,请调用 Concurrency::Context::Oversubscribe 方法,并将 _BeginOversubscription 参数设置为 true。 当在并发运行时创建的线程上启用过度订阅时,它导致该运行时创建一个附加线程。 当需要过度订阅的所有任务完成后,调用 Context::Oversubscribe,并将 _BeginOversubscription 参数设置为 false。
您可以从当前上下文多次启用过度订阅,但禁用它的次数必须与启用它的次数相同。 也可以嵌套过度订阅;也就是说,由使用过度订阅的另一任务创建的任务也可以过度订阅其上下文。 但是,如果嵌套的任务和其父任务属于同一上下文,则只有对 Context::Oversubscribe 的最外层调用会导致创建附加线程。
提示
如果先禁用过度订阅再启用它,则运行时将引发 Concurrency::invalid_oversubscribe_operation。
示例
有关使用过度订阅来抵销通过网络连接读取数据导致的延迟的示例,请参见如何:使用过度订阅抵消延迟。
请参见
任务
概念
其他资源
修订记录
日期 |
修订记录 |
原因 |
---|---|---|
2010 年 7 月 |
重新组织了内容。 |
信息补充。 |