使用异步
异步中提供了一个名为promise的模板类,用于传输异步变量。
使用时需要包含future头文件。
promise包含以下特性:
- 通过模板的方式存储变量值,并通过创建对象的future来获取结果。
- promise使用set_value来设置变量的值,且只能使用一次。
- future使用get方法以阻塞的方式获取promise设置的值。
通过一个异步设置字符串的案例来熟悉:
1 |
|
观察上述案例的执行结果:
首先出现”Get = “然后程序被阻塞等待异步运行结果;随后是”BeginSetValue”;接着打印SetPromiseValue,在p被赋值后立刻打印出来;最后才是”EndSetValue”。
将函数的运行与结果分离
对于一些情况,我们希望函数的运行与返回值是分离的,这时就需要使用函数打包调用。
函数打包主要使用packaged_task来实现。
提供以下案例:
1 | void FuncPackage(int index) |
package_task中模板类型为返回值和括号中的参数类型
观察上述执行结果:
先是打印”Pack index = 100”;而后是”BeginTask”;等待之后打印”Get Ans = Pack Func”。
但上述代码解决了基本需求,但也确实存在一些问题:比如打包的函数执行因为某些原因花费了许多时间,但get方法却一直等待结果可能会导致死锁等问题,所以需要对延时情况做一些处理:
我们不直接wait_for,而是改用循环多次查询运行结果来处理延时以供参考
1 | // 处理延时情况,防止一直阻塞 |
使用async实现异步
Aysnc异步提供了两种方法:创建子线程与不创建子线程。
不创建子线程异步
不创建子线程需要创建时提供launch::deferred来实现:
1 | void ThreadNoCreate(int index) |
使用index只是为了提供有参数情况参考,不具有意义。
通过打印两个线程id发现实际是在同一个线程中执行的。
创建子线程
创建子线程时async提供的默认方法,只需要把launch::deferred省去即可:
1 | void test() |
除了线程id不同外,两者最终执行效果没什么差别。
总结
主要介绍了三种实现异步的方式:
- 通过promise与future来实现。
- 通过打包函数实现。
- 使用aysnc实现,其中aysnc提供了创建子线程与不创建子线程两种方式。
- 本文作者: KongXinQing
- 本文链接: https://13114987559.github.io/2024/04/06/note/C++多线程入门:线程异步/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!