自 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. [进程管理]Linux进程状态解析之T、Z、X

             Linux进程状态:T (TASK_STOPPED or TASK_TRACED),暂停状态或跟踪状态.          向进程发送一个SIGSTOP信号,它就会因响应该信号而进入 ...

  2. [进程管理] 理解 Linux 的处理器负载均值

    原文链接: http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages http://www.gracecode. ...

  3. 纯HTML课表

    table标签构造课表 table标签常用于制作表格以及简单布局,于是我就玩了下table标签,用table标签也能构造出很漂亮的页面呢,虽然在博客页面加入与实际打开页面稍微有点出入,但还是可以接受的 ...

  4. JS面向对象,创建,继承

    很开心,最近收获了很多知识,而且发现很多东西,以前理解的都是错的,或者是肤浅的,还以为自己真的就get到了精髓,也很抱歉会影响一些人往错误的道路上走,不过这也告诉了我们,看任何一篇文章都不能盲目的去相 ...

  5. 如何解决 chrome 58 版本更新导致的 fiddler https 抓包不可用问题

    注意!如果该方法不生效,请先卸载原有 fiddler 后再进行新版本 fiddler 安装步骤即可. chrome 于(上周?上上周?)推送了chrome 58 版本的更新,这次更新中直接去掉了证书未 ...

  6. c#常用方法和类

    1.  数据类型转换函数 Convert.ToXXX(); XXX.Parse(); XXX.TryParse(); 2. 日期相关的类与函数 获取系统当前日期(含时间):DateTime.Now 获 ...

  7. 最大流算法之Dinic

    引言: 在最大流(一)中我们讨论了关于EK算法的原理与代码实现,此文将讨论与EK算法同级别复杂度(O(N^2M))的算法--Dinic算法. Dinic算法用到的思想是图的分层结构,通过BFS将每一个 ...

  8. 欲练JS,必先攻CSS——前端修行之路

    今天我讲的主题是css,具体聊一下我大概的css学习历史,分享一些干货,希望这次分享对大家有所启发和帮助. 个人的css历史: 说说自己的css学习的历史,12年,当时是老师手把手1对1教我div+f ...

  9. JAVA CyclicBarrier类详解

    一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时CyclicBarrie ...

  10. ng-class改变css样式

    而在这所谓的样子当然就是改变其css的属性,而实现能动态的改变其属性值,必然只能是更换其class属性 这里有三种方法: 第一种:通过数据的双向绑定(不推荐) 第二种:通过对象数组 第三种:通过key ...