windows C++ 并行编程-并发和UWP(一)

本文介绍当在通用 Windows 运行时 (UWP) 应用中使用任务类生成基于 Windows 线程池的异步操作时要谨记的一些要点。

异步编程的使用是 Windows 运行时应用模型中的关键组成部分,因为它能使应用保持对用户输入的响应。 可以启动长期运行的任务,而不必阻止 UI 线程,并且可以在以后接收任务的结果。 也可以在任务在后台运行时取消任务和接收进度通知。 文档 C++ 中的异步编程提供 Visual C++ 中可用于创建 UWP 应用的异步模式的概述。 该文档介绍如何使用和创建异步 Windows 运行时操作链。 本节介绍如何使用 ppltasks.h 中的类型生成可供另一个 Windows 运行时组件使用的异步操作,以及如何控制异步工作的执行方式。

在 UWP 应用中,可以使用并行模式库 (PPL) 和异步代理库。 但是,不能使用任务计划程序或资源管理器。 本文介绍 PPL 提供的附加功能,这些功能仅适用于 UWP 应用,不适用于桌面应用。

UWP中使用并发编程的要点

  • 使用 concurrency::create_async 来创建可供其他组件(可能用除 C++ 之外的语言编写)使用的异步操作;
  • 使用 concurrency::progress_reporter 向调用您的异步操作的组件报告进程通知;
  • 使用取消标记实现内部异步操作的取消;
  • create_async 函数的行为取决于传递给它的工作函数的返回类型。 返回任务( task<T> 或 task<void>)的工作函数在调用了 create_async的上下文中同步运行。 返回 T 或 void 的工作函数在任意上下文中运行;
  • 可以使用 concurrency::task::then 方法创建一个可依次运行的任务链。 在 UWP 应用中,任务延续的默认上下文取决于此任务的构造方式。 如果是通过向任务构造函数传递异步操作,或通过传递可返回异步操作的 lambda 表达式创建的任务,那么此任务所有延续的默认上下文是当前上下文。 如果任务不是从异步操作构造的,那么默认情况下,对任务的延续使用任意上下文。 可以用 concurrency::task_continuation_context 类重写默认上下文;
创建异步操作

可以使用并行模式库 (PPL) 中的任务和延续模型定义后台任务以及上一任务完成时要运行的其他任务。 这个功能由 concurrency::task 类提供。 

Windows 运行时是可用于创建仅在特殊操作系统环境中运行的 UWP 应用的编程接口。 此类应用使用经授权的函数、数据类型和设备,并且从 Microsoft Store 进行分配。 Windows 运行时由应用程序二进制接口 (ABI) 表示。 ABI 是一种基础二进制协定,该协定允许 Visual C++ 等编程语言使用 Windows 运行时 API。

通过使用 Windows 运行时,可以使用各种编程语言的最佳功能并将它们合并到一个应用中。 例如,可以在 JavaScript 中创建 UI,在 C++ 组件中执行计算密集型应用程序逻辑。 在后台执行这些计算密集型操作的能力是使 UI 保持响应状态的一个关键因素。 因为 task 类特定于 C++,所以必须使用 Windows 运行时接口将异步操作传达给其他组件(可能用除 C++ 之外的语言编写)。 Windows 运行时提供四个接口,可以使用它们来表示异步操作:

  • Windows::Foundation::IAsyncAction表示异步操作。
  • Windows::Foundation::IAsyncActionWithProgress<TProgress>表示报告进度的异步操作。
  • Windows::Foundation::IAsyncOperation<TResult>表示返回结果的异步操作。
  • Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>表示返回结果并报告进度的异步操作。

动作 的概念是指异步任务不生成值(想一想返回 void的函数)。 操作 的概念是指异步任务确实会生成值。 进程 的概念是指任务可以向调用方报告进程消息。 JavaScript、.NET Framework 和 Visual C++ 均提供自己的方式来创建这些接口的实例,以便跨 ABI 边界使用。 对于 Visual C++,PPL 提供 concurrency::create_async 函数。 此函数会创建表示任务完成的 Windows 运行时异步动作或操作。 create_async 函数采用一个工作函数(通常是 lambda 表达式),以内部方式创建 task 对象,并将此任务包装到四个异步 Windows 运行时接口之一中。

仅在必须创建可从另一语言或另一 Windows 运行时组件访问的功能时才使用 create_async。 当知道操作是由 C++ 代码在同一组件中生成和使用时,可以直接使用 task 类。

create_async 的返回类型由其参数的类型决定。 例如,如果工作函数不返回值并且不报告进度,则 create_async 返回 IAsyncAction。 如果工作函数不返回值,但还会报告进度,则 create_async 返回 IAsyncActionWithProgress。 若要报告进度,请提供 concurrency::progress_reporter 对象作为工作函数的参数。 报告进度的能力使您能够报告已执行的工作量和仍然剩余的工作量(比如以百分比表示)。 还可以使您在结果可用时报告结果。

IAsyncAction、 IAsyncActionWithProgress<TProgress>、 IAsyncOperation<TResult>和 IAsyncActionOperationWithProgress<TProgress, TProgress> 接口均提供可以使您取消异步操作的 Cancel 方法。 task 类与取消标记一起使用。 当使用取消标记来取消工作时,运行时不会启动订阅此标记的新工作。 已处于活动状态的工作会监控其取消标记并在可能时停止。 文档 Cancellation in the PPL中更详细地介绍了这种机制。 可通过两种方式将任务取消与 Windows 运行时 Cancel 方法关联起来。 首先,可以定义传递给 create_async 的工作函数以采用 concurrency::cancellation_token 对象。 当调用 Cancel 方法时,将取消此取消标记,并将常规取消规则应用于支持 create_async 调用的基础 task 对象。 如果没有提供 cancellation_token 对象,则基础 task 对象会隐式定义一个。 在需要以协作方式响应工作函数中的取消时,可定义一个 cancellation_token 对象。 示例:使用 C++ 和 XAML 在 Windows 运行时应用中控制执行部分演示了一个有关如何在通用 Windows 平台 (UWP) 应用(使用自定义的 Windows 运行时 C++ 组件)中使用 C# 和 XAML 执行取消的示例。

在一个任务延续链中,当取消了取消标记时,应始终清理状态,然后调用 concurrency::cancel_current_task。 如果是提早返回而不是调用 cancel_current_task,则操作将转换为已完成状态而非已取消状态。

下表总结了在应用程序中可用于定义异步操作的组合。

可以从传递给 task 函数的工作函数返回一个值或一个 create_async 对象。 这些变体会产生不同的行为。 当返回一个值时,工作函数会包装到 task 中,以使其可在后台线程上运行。 此外,基础 task 使用隐式取消标记。 相反,如果返回 task 对象,则工作函数会同步运行。 因此,如果返回 task 对象,请确保工作函数中的任何较长操作作为任务运行,以使应用程序能够保持响应状态。 此外,基础 task 不使用隐式取消标记。 因此,在从 cancellation_token 返回 task 对象时,如果需要取消支持,则需定义工作函数以采用 create_async对象。

下面的示例演示创建可供另一 Windows 运行时组件使用的 IAsyncAction 对象的各种方式。

// Creates an IAsyncAction object and uses an implicit cancellation token.
auto op1 = create_async([]
{
    // Define work here.
});

// Creates an IAsyncAction object and uses no cancellation token.
auto op2 = create_async([]
{
    return create_task([]
    {
        // Define work here.
    });
});

// Creates an IAsyncAction object and uses an explicit cancellation token.
auto op3 = create_async([](cancellation_token ct)
{
    // Define work here.
});

// Creates an IAsyncAction object that runs another task and also uses an explicit cancellation token.
auto op4 = create_async([](cancellation_token ct)
{
    return create_task([ct]()
    {
        // Define work here.
    });
});
Contents 开发桌面应用 设置开发环境 系统要求 安装开发人员工具 启用设备进行开发 开发人员模式功能和调试 创建一个开发者帐户 入门 概述 适用于 Windows 应用的 Visual Studio 模板 生成适用于 Windows 11 的应用 让你的应用在 Windows 11 上出色表现 设计和 UI 概述 Windows 11 中的设计 Windows 11 设计原则 Windows 11 签名体验 Geometry 颜色 分层和提升 材料 图标 版式 设计基础知识 概述 应用设计简介 导航基础知识 概述 实现基本导航 导航历史记录和向后导航 命令基础知识 内容基础知识 教程 创建用户界面 创建自适应布局 设置控件的样式 布局 概述 页面布局 屏幕大小和断点 响应式设计技术 使用 XAML 的布局 显示多个视图 显示多个视图 使用 AppWindow 使用 ApplicationView 对齐、边距和填充 面板 概述 教程:使用布局面板 拆分视图 自定义面板 自定义面板示例:BoxPanel 附加的布局 转换 概述 3D 透视效果 Z 深度和阴影 控制 概述 控件和事件简介 命令处理简介 基本输入 按钮 复选框 组合框和列表框 超链接 单选按钮 评分控件 滑块 切换开关 集合 概述 列表视图和网格视图 翻转视图 PipsPager 树视图 ItemsRepeater 项目容器和模板 项目容器和模板 数据模板选择 列表视图项模板 网格视图项模板 选择和交互 集合命令处理 “选择模式”概述 轻扫 下拉刷新 筛选集合 其他集合选项和自定义 反转列表 嵌套 UI 对话框和浮出控件 概述 对话框 浮出控件 教学提示 窗体 媒体、图形和形状 动画图标 图像和图像画笔 墨迹 媒体播放 自定义传输控件 形状 Web 视图 菜单和工具栏 菜单和上下文菜单 命令栏 命令栏浮出控件 菜单浮出控件和菜单栏 导航 痕迹导航栏 列表/详细信息 导航视图 Pivot 选项卡视图 人员 联系人卡片 头像图片 选取器 颜色选取器 日期和时间控件 日历日期选取器 日历视图 日期选取器 时间选取器 滚动和布局 Expander 滚动和平移控件 语义式缩放 双窗格视图 状态和信息 进度 工具提示 信息栏 文本 概述 自动建议框 文本块 RTF 块 文本框 富编辑框 密码框 数字框 标签 内容链接 手写视图 样式 概述 颜色 版式 图标 概述 应用图标和徽标 Segoe MDL2 图标 亚克力 Mica 显示焦点 声音 写入样式 XAML 画笔 XAML 样式 XAML 控件模板 ResourceDictionary 和 XAML 资源引用 XAML 主题资源 间距 角半径 移动 概述 计时和缓动 方向性和引力 运动练习 页面过渡 连贯的动画 视差 XAML 中的动画 属性动画 情节提要动画 关键帧以及缓动函数动画 Shell Toast 通知 UX 指南 发送本地 Toast C# 应用 C++ UWP 应用 C++ WRL 应用 其他应用 Toast 内容 Content 架构 计划 toast 其他功能 自定义音频 进度条 挂起更新 自定义时间戳 集合 标头 通知侦听器 已过时 锁屏提醒通知 推送通知 概述 WNS 优先级 将 WNS 流量加入允许列表 由推送通知向导生成的代码 任务栏 将应用固定到任务栏 标题栏 动态磁贴 辅助磁贴 指南 固定到“开始”屏幕 固定到任务栏 桌面应用程序 磁贴内容 磁贴内容架构 特殊磁贴模板 发送本地磁贴通知 可追踪的磁贴通知 主要磁贴 API 磁贴和 Toast 通知的语言、比例和高对比度支持 杂项 通知可视化工具 通知传递方法 通知通道类型 使用 Webpush 和 VAPID 的备用通道 定期通知 输入和交互 概述 输入基础版 指针输入 凝视 笔和 Windows Ink 教程:向应用添加墨迹支持 识别笔划墨迹 存储和检索笔划墨迹 添加 InkToolbar 触摸 鼠标 Keyboard 访问键 键盘加速键 键盘事件 适用于键盘、手柄、遥控器和辅助功能工具的焦点导航 编程焦点导航 响应触摸键盘的存在 使用输入范围更改触摸键盘 文本输入 自定义文本输入 文本缩放 选择文本和图像 输入法编辑器 输入法编辑器要求 ......
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值