自 VS2010 起,微软就在 CRT 中集成了并发运行时(Concurrency Runtime),并行模式库(PPL,Parallel Patterns Library)是其中的一个重要组成部分。7 年过去了,似乎大家都不怎么Care这个事情,相关文章少少且多是蜻蜓点水。实际上这个库的设计相当精彩,胜过 C++ 标准库中 future/promise/async 系列许多,所以计划写一个系列探讨 PPL 在实际项目中应用中的各种细节。

好了,从最简单的代码开始,先演示下如何使用 task 类和 lambda 表达式创建一个并行任务:

// final_answer.cpp
// compile with: /EHsc #include <ppltasks.h>
#include <iostream> using namespace concurrency;
using namespace std; int main(int argc, char *argv[])
{
task<int> final_answer([]
{
return ;
}); cout << "The final answer is: " << final_answer.get() << endl; return ;
}

使用 Visual Studio 命令行工具编译

cl /EHsc final_answer.cpp

执行结果为:

The final answer is: 42

task 类的原型如下:

template<typename _ReturnType>
class task;

其模板参数 _ReturnType 是任务返回值类型。 task:get 方法则用于获取返回值,原型如下:

_ReturnType get() const;

task 类的构造函数原型:

template<typename T>
__declspec(noinline) explicit task(T _Param);

可以看到这是个模板函数,其参数 _Param 可以是 lambda 表达式、函数对象、仿函数、函数指针等可以以 _Param() 形式调用的类型,或者 PPL 中的 task_completion_event<result_type> 类型。因此可以使用各种灵活的方式构造 task 对象,其中 lambda 表达式无疑是最方便常用的一种。

接下来我们修改上面的程序,打印出线程 id 以便观察并行任务的执行情况。

// final_answer_1.cpp
// compile with: /EHsc #include <ppltasks.h>
#include <iostream>
#include <thread> using namespace concurrency;
using namespace std; int main(int argc, char *argv[])
{
cout << "Major thread id is: " << this_thread::get_id() << endl; task<int> final_answer([]
{
cout << "Thread id in task is:" << this_thread::get_id() << endl;
return ;
}); cout << "The final answer is: " << final_answer.get() << endl; return ;
}

继续编译执行,得到输出结果:

Major thread id is: 164824

Thread id in task is: 164824

The final answer is: 42

注意两个线程 id 是相同的,很有些意外,任务是在主线程执行的而非预计的其他后台工作线程。实际上这是 PPL 的优化策略造成的。

再修改下程序,在 task 对象构造完成后加一个 sleep 调用挂起当前线程一小段时间:

int main(int argc, char *argv[])
{
cout << "Major thread id is: " << this_thread::get_id() << endl; task<int> final_answer([]
{
cout << "Thread id in task is:" << this_thread::get_id() << endl;
return ;
}); this_thread::sleep_for(chrono::milliseconds()); cout << "The final answer is: " << final_answer.get() << endl; return ;
}

这次输出结果发生了变化:

Major thread id is: 173404

Thread id in task is: 185936

The final answer is: 42

PPL 使用了一个新的线程执行并行任务,实际上 PPL 是使用了线程池来执行被调度到的任务。

而在上一个程序中,由于没有 sleep,也没有其他耗时的代码,执行到 task::get 方法时并行任务尚未被调度所以直接在当前线程执行该任务,这样就节省了两次线程切换的开销

MSDN 中对 task::wait 方法的说明:

It is possible for wait to execute the task inline, if all of the tasks dependencies are satisfied, and it has not already been picked up for execution by a background worker.

task::get 方法的内部实现会先调用 task::wait 方法所以有同样的效果。

本章小结:

1. task 类对象构造完成后即可被调度执行;

2. 并行有可能被优化在当前线程执行;

留一个问题,如果 task 对象构造后马上析构,该并行任务是否会被调度执行呢?

本章代码使用 visual studio community 2013 编译调试通过。

本章参考文档:

How to: Create a Task that Completes After a Delay 
task Class (Concurrency Runtime)

并行模式库PPL应用实战(一):使用task类创建并行任务的更多相关文章

  1. .NET并行编程1 - 并行模式

    设计模式——.net并行编程,清华大学出版的中译本. 相关资源地址主页面: http://parallelpatterns.codeplex.com/ 代码下载: http://parallelpat ...

  2. 有助于提高你的 Web 开发技能的7个模式库

    正如语言风格指南一样,模式库有两个主要用途.首先,是它们提供了一组编码或设计标准,Web 开发团队可以在整个网站中应用,有助于保持一致的编码实践和外观:其次,对于要学习网页设计最佳实践来说是宝贵的财富 ...

  3. Java多线程--并行模式与算法

    Java多线程--并行模式与算法 单例模式 虽然单例模式和并行没有直接关系,但是我们经常会在多线程中使用到单例.单例的好处有: 对于频繁使用的对象可以省去new操作花费的时间: new操作的减少,随之 ...

  4. 并行模式之Guarded Suspension模式

    并行模式之Guarded Suspension模式 一).Guarded Suspension: 保护暂存模式 应用场景:当多个客户进程去请求服务进程时,客户进程的请求速度比服务进程处里请求的速度快, ...

  5. 并行模式之Master-Worker模式

    并行模式之Master-Worker模式 一).Master-Worker模式 作用: 将一个大任务分解成若干个小任务,分发给多个子线程执行. 注: 将大任务分解成小任务,小任务的实现逻辑要相同. 二 ...

  6. oracle并行模式

    参考链接:oracle并行模式(Parallel),深入理解Oracle的并行操作(原创),oracle使用并行踩过的坑 1. 语法(这个可以加到insert.delete.update.select ...

  7. 【C/C++开发】C++静态库与动态库以及在Linux和Windows上的创建使用

    原文出处: 吴秦的博客    这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学 ...

  8. .NET 4 并行(多核)编程系列之三 从Task的取消

    原文:.NET 4 并行(多核)编程系列之三 从Task的取消 .NET 4 并行(多核)编程系列之三 从Task的取消 前言:因为Task是.NET 4并行编程最为核心的一个类,也我们在是在并行编程 ...

  9. SSIS从理论到实战,再到应用(1)----创建自己的第一个包

    原文:SSIS从理论到实战,再到应用(1)----创建自己的第一个包 其实,如果你使用sql2008的导出导入工具的时候,你就已经在使用包了. 目标:使用sql2008 导入导出工具,导入excel数 ...

随机推荐

  1. 解决IE无法访问localhost问题

    前几天新安装了win10和webstorm16,发现系统是的IE浏览器是IE11,调试时无法正常显示网页: 一开始以为是系统没有写入密钥,无法获得权限,查了一下后发现是局域网设置不正确. 作以下设置可 ...

  2. JavaFx自定义Tab-Order

    title: JavaFx自定义Tab-Order Tab-order是什么?在界面上当你按tab键触发焦点转移的功能,这就是tab order.但是Javafx有个缺陷就是不方便自己设置tab-or ...

  3. highlight.js 代码高亮插件的使用

    在网页使用过程中,经常会用到代码的展示.而不同颜色的代码,可以让代码看起来更直观,也更美观. 找了几个不同的插件,觉得highlight的插件比较实用,而且用起来炒鸡简单. 比如这样: 首先,我们先下 ...

  4. 解析Excel文件并把数据存入数据库

    前段时间做一个小项目,为了同时存储多条数据,其中有一个功能是解析Excel并把其中的数据存入对应数据库中.花了两天时间,不过一天多是因为用了"upload"关键字作为URL从而导致 ...

  5. 使用DocFX生成文档

    使用DocFX命令行生成文档 使用docfx 命令 1.下载 https://github.com/dotnet/docfx/releases 2.使用 创建初始项目 docfx init -q 此命 ...

  6. 区划代码 node 版爬虫尝试

    前言 对于区划代码数据,很多人都不会陌生,大多公司数据库都会维护一份区划代码,包含省市区等数据.区划信息跟用户信息息息相关,往往由于历史原因很多数据都是比较老的数据,且不会轻易更改.网上也有很多人提供 ...

  7. Java学习笔记——浅谈数据结构与Java集合框架(第三篇、Map)

    桃李春风一杯酒,江湖夜雨十年灯 --寄黄几复 之前图上写错了,是Hashtable类.t是小写的,它是个很古老的类,以至于命名都没有那么规范.. HashMap HashMap就是存储key-valu ...

  8. TCP协议详解---上

    TCP头格式 注意以下几点: TCP的包是没有IP地址的,那是IP层上的事.但是有源端口和目标端口. 一个TCP连接需要四个元组来表示是同一个连接(src_ip, src_port, dst_ip, ...

  9. winform无边框窗口拖动

    无边框的窗口想拖动,只需要在置顶的容器上添加对应的mousedown 和 mousemove 事件就可以实现了.代码如下: //拖动窗口 private Point mPoint = new Poin ...

  10. su 切换用户的提示"This account is currently not available"

    su 切换ivalue用户时,提示"This account is currently not available"; 首先进入/etc/passwd文件中是否添加ivalue用户 ...