std::packagedtask概念和使用方法
一、概念
std::packaged_task
是 C++ 标准库中的一个类模板,它将一个可调用对象(如函数、函数对象或 lambda 表达式)包装起来,使得这个可调用对象可以作为异步任务来执行,并可以通过std::future
对象获取其结果。
std::packaged_task
的主要目的是将任务的执行与结果的获取分离,方便在多线程环境中进行异步编程。
二、使用方法
1. 包含头文件
#include <iostream>
#include <future>
2. 基本用法
int add(int a, int b) {return a + b;}int main() {// 创建一个 packaged_task 对象,包装 add 函数std::packaged_task<int(int, int)> task(add);// 获取与 packaged_task 关联的 future 对象std::future<int> result = task.get_future();// 在另一个线程中执行任务std::thread t(std::move(task), 3, 4);// 获取任务结果int sum = result.get();std::cout << "The sum is: " << sum << std::endl;t.join();return 0;}
在这个例子中,首先创建了一个std::packaged_task<int(int, int)>
对象,将add
函数包装起来。然后通过task.get_future()
获取与这个任务关联的std::future<int>
对象。接着在一个新线程中执行任务,通过std::move(task)
将任务转移到新线程中执行。最后,调用result.get()
获取任务的结果。
3. 使用 lambda 表达式
int main() {std::packaged_task<int()> task([](){ return 5 + 3; });std::future<int> result = task.get_future();std::thread t(std::move(task));int sum = result.get();std::cout << "The sum is: " << sum << std::endl;t.join();return 0;}
这里使用 lambda 表达式创建了一个简单的加法任务,并通过std::packaged_task
和std::future
来获取结果。
4. 异常处理
如果包装的可调用对象抛出异常,这个异常将在调用std::future
对象的get
成员函数时重新抛出。
int divide(int a, int b) {if (b == 0) {throw std::runtime_error("Division by zero");}return a / b;}int main() {std::packaged_task<int(int, int)> task(divide);std::future<int> result = task.get_future();std::thread t(std::move(task), 10, 0);try {int quotient = result.get();std::cout << "The quotient is: " << quotient << std::endl;} catch (const std::exception& e) {std::cout << "Caught an exception: " << e.what() << std::endl;}t.join();return 0;}
std::packaged_task
在异步编程中非常有用,可以方便地将任务封装起来并获取其结果,同时可以与std::thread
、std::async
等结合使用,提高程序的并发性和性能。