C++11多线程:std::packaged_task基本使用-打包任务,包装任务;std::promise的类模板使用。

2023-11-02

文章目录


前言

语言:c++11
(1)std:packaged_task:通过std::packaged_task 来把各种可调用对象包装起来,方便将来作为线程入口函数来调用。;
(2)std::promise:我们能够在某个线程中给它赋值,然后我们可以在其他线程中,把这个取值出来用。
(3)代码案例。


一、std::packaged_task

1.1 函数介绍

std::packaged_task:打包任务,把任务包装起来。

(1)是个类模板,它的模板参数是 各种可调用对象;通过std::packaged_task 来把各种可调用对象包装起来,方便将来作为线程入口函数来调用
(2)packaged_task包装起来的可调用对象还可以直接调用,所以从这个角度来讲,packaged_task对象,也是 一个可调用对象;

1.2 使用步骤

1.2.1 代码案例1

包装起来的可调用对象,作为函数入口函数来调用。

代码实例:

#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <SDKDDKVer.h>
#include <vector>
#include <map>
#include <string>
#include <thread>
#include <list>
#include <mutex>
#include <future>
int mythread1(int mypar) //线程入口函数
{
	cout << "mythrea() start" << " threadid = " << std::this_thread::get_id() << endl;	//打印新线程id
	std::chrono::milliseconds dura(5000);	//订一个5秒的时间
	std::this_thread::sleep_for(dura);	//休息了一定时长
	cout << "mythread() end" << " threadid = " << std::this_thread::get_id() << endl;	//打印新线程id
	return 5;
}

int main()
{
	//二:std::packaged_task:打包任务,把任务包装起来
	//是个类模板,它的模板参数是 各种可调用对象;通过std::packaged_task 来把各种可调用对象包装起来,方便将来作为线程入口函数来调用;

	cout << "main" << " threadid = " << std::this_thread::get_id() << endl;
	std::packaged_task<int(int)> mypt(mythread1);
	//我们把函数mythread通过packaged_task包装起来
	std::thread t1(std::ref(mypt), 1);
	//线程直接开始执行,第二个参数 作为线程入口函数的参数。
	t1.join();
	//等待线程执行完毕。
	std::future<int> result = mypt.get_future();
	//std::future对象里包含有线程入口函数的返回结果,这里result保存mythread返回的结果。
	cout << result.get() << endl;
	cout << "I Love China!" << endl;

	return 0;
}

运行截图:
在这里插入图片描述

1.2.2 代码案例2

包装起来的可调用对象,直接被调用。

代码如下(示例):

#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <SDKDDKVer.h>
#include <vector>
#include <map>
#include <string>
#include <thread>
#include <list>
#include <mutex>
#include <future>
int mythread1(int mypar) //线程入口函数
{
	cout << "mythrea() start" << " threadid = " << std::this_thread::get_id() << endl;	//打印新线程id
	std::chrono::milliseconds dura(5000);	//订一个5秒的时间
	std::this_thread::sleep_for(dura);	//休息了一定时长
	cout << "mythread() end" << " threadid = " << std::this_thread::get_id() << endl;	//打印新线程id
	return 5;
}

int main()
{
	//packaged_task包装起来的可调用对象还可以直接调用,所以从这个角度来讲,packaged_task对象,也是 一个可调用对象;

	cout << "main" << " threadid = " << std::this_thread::get_id() << endl;

	std::packaged_task<int(int)> mypt([](int mypar) {
		cout << mypar << endl;
		cout << "mythread() start" << " threadid = " << std::this_thread::get_id() << endl;
		//打印新线程id
		std::chrono::milliseconds dura(5000);
		//订一个5秒的时间
		std::this_thread::sleep_for(dura);
		//休息了一定时长
		cout << "mythread() end" << " threadid = " << std::this_thread::get_id() << endl;
		//打印新线程id
		return 5;
	});

	//std::thread t1(sed::ref(mypt), 1);
	//线程直接开始执行,第二个参数 作为线程入口函数的参数。
	//t1.join();
	//等待线程执行完毕。
	//std::future<int> result = mypt.get_future();
	//std::future对象里包含有线程入口函数的返回结果,这里result保存mythread返回的结果。
	//cout << result.get() << endl;
	//cout << "I Love China!" << endl;

	mypt(105);
	//直接调用,相当于函数调用;
	std::future<int> result = mypt.get_future();
	cout << result.get() << endl;

	return 0;
}

运行截图:
在这里插入图片描述

二、std::promise

2.1 基本介绍

  • std::promise,类模板
  • 我们能够在某个线程中给它赋值,然后我们可以在其他线程中,把这个取值出来用;

总结:通过promise保存一个值,在将来某个时刻我们通过把一个future绑定到这个promise上来得到这个绑定的值;


2.2 使用步骤

2.2.1 代码案例

void mythread2(std::promise<int> &tmpp, int calc)	//大家注意第一个参数
{
	//做一系列复杂的操作
	calc++;
	calc *= 10;
	//做其他运行,比如整整花费了5秒钟;

	std::chrono::milliseconds dura(5000);
	//订一个5秒的时间
	std::this_thread::sleep_for(dura);
	//休息了一定时长

	//终于计算出结果了
	int result = calc;
	//保存结果
	tmpp.set_value(result);
	//结果我保存到了tmpp这个对象中;
	return;
}

void mythread3(std::future<int> &tmpf)
{
	auto result = tmpf.get();
	cout << "mythread2 result = " << result << endl;
	return;
}

int main()
{
	//三:std::promise,类模板
	//我们能够在某个线程中给它赋值,然后我们可以在其他线程中,把这个取值出来用;
	//总结:通过promise保存一个值,在将来某个时刻我们通过把一个future绑定到这个promise上来得到这个绑定的值;
	std::promise<int> myprom;
	//声明一个std::promise对象myprom,保存的值类型为int;
	std::thread t1(mythread2, std::ref(myprom), 4);
	t1.join();

	//获取结果值
	std::future<int> ful = myprom.get_future();
	//promise和future绑定,用于获取线程返回值
	//auto result = ful.get();
	//get只能调用一次,不能调用多次
	//cout << "result = " << result << endl;

	std::thread t2(mythread3, std::ref(ful));
	t2.join();
	//等mythread2线程执行完毕

	cout << "end!" << endl;

	//四:小结:到底怎么用,什么时候用;
	//我们学习这些东西的目的,并不是要把他们都用在咱们自己的实际开发中。
	//相反,如果我们能够用最少的东西能够写出一个稳定、高效地多线程程序,更值得赞赏;
	//我们为了成长,必须要要阅读一些高手写的代码,从而快速实现自己代码的积累,我们的技术就会有一个大幅度的提升;
	//老师更愿意将学习这些内容的理由解释为:为我们将来能够读懂高手甚至大师写的代码而铺路;

	return 0;
}

运行截图:
在这里插入图片描述

总结

(1)了解std::packaged_task的基本使用;
(2)了解两种调用方式:作为函数接口被调用直接调用

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11多线程:std::packaged_task基本使用-打包任务,包装任务;std::promise的类模板使用。 的相关文章

  • WPF DataGrid 多选

    我读过几篇关于这个主题的文章 但很多都是来自 VS 或框架的早期版本 我想做的是从 dataGrid 中选择多行并将这些行返回到绑定的可观察集合中 我尝试创建一个属性 类型 并将其添加到可观察集合中 它适用于单个记录 但代码永远不会触发多个
  • 调用 McAfee 病毒扫描引擎

    我收到客户的请求 要求使用他们服务器上的 McAfee 病毒扫描将病毒扫描集成到应用程序中 我做了一些调查 发现 McScan32 dll 是主要的扫描引擎 它导出各种看起来有用的函数 我还发现提到了 McAfee Scan Engine
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • 对类 static constexpr 结构的未定义引用,g++ 与 clang

    这是我的代码 a cp p struct int2 int x y struct Foo static constexpr int bar1 1 static constexpr int2 bar2 1 2 int foo1 return
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置
  • 使用 WGL 创建现代 OpenGL 上下文?

    我正在尝试使用 Windows 函数创建 OpenGL 上下文 现代版本 基本上代码就是 创建窗口类 注册班级 创建一个窗口 choose PIXELFORMATDESCRIPTOR并设置它 创建旧版 OpenGL 上下文 使上下文成为当前

随机推荐