C++编程中`packaged_task`的使用详解

张开发
2026/4/7 21:33:34 15 分钟阅读

分享文章

C++编程中`packaged_task`的使用详解
C编程中packaged_task的使用详解在C的多线程编程领域异步任务处理是一个重要的概念。packaged_task作为C11引入的一个工具为异步任务的封装和结果获取提供了便利。下面将深入探讨packaged_task的使用方法。packaged_task的基本概念packaged_task是一个模板类它将一个可调用对象如函数、lambda表达式等与一个std::future关联起来。当packaged_task对象被调用时它会执行关联的可调用对象并将结果存储在与之关联的std::future对象中。通过std::future我们可以在后续的代码中获取异步任务的结果。创建packaged_task对象要使用packaged_task首先需要创建它的对象。创建时需要指定模板参数该参数表示可调用对象的返回类型。例如如果要封装一个返回int类型的函数可以这样创建packaged_task对象#includeiostream#includefuture#includethreadintmyFunction(inta,intb){returnab;}intmain(){// 创建packaged_task对象关联myFunction函数std::packaged_taskint(int,int)task(myFunction);// 获取与packaged_task关联的future对象std::futureintresulttask.get_future();return0;}在上述代码中std::packaged_taskint(int, int)表示这个packaged_task关联的可调用对象接受两个int类型的参数并返回一个int类型的结果。通过调用get_future()方法我们得到了一个std::futureint对象用于后续获取任务的结果。运行packaged_task关联的任务创建packaged_task对象后需要运行它关联的任务。有几种常见的方式可以实现这一点方式一在当前线程中直接调用可以直接调用packaged_task对象就像调用普通函数一样。这种方式适用于在当前线程中同步执行任务的场景。#includeiostream#includefutureintmyFunction(inta,intb){returnab;}intmain(){std::packaged_taskint(int,int)task(myFunction);std::futureintresulttask.get_future();// 在当前线程中直接调用packaged_task对象task(3,4);// 通过future对象获取结果intsumresult.get();std::coutThe sum is: sumstd::endl;return0;}在上述代码中通过task(3, 4)调用了packaged_task对象执行了关联的myFunction函数并将结果存储在result这个std::future对象中。最后通过result.get()获取了任务的结果。方式二在新线程中运行更常见的方式是将packaged_task对象移动到一个新线程中运行实现异步任务处理。#includeiostream#includefuture#includethreadintmyFunction(inta,intb){returnab;}intmain(){std::packaged_taskint(int,int)task(myFunction);std::futureintresulttask.get_future();// 将packaged_task对象移动到新线程中运行std::threadt(std::move(task),3,4);t.detach();// 在这里可以进行其他操作...// 通过future对象获取结果intsumresult.get();std::coutThe sum is: sumstd::endl;return0;}在上述代码中使用std::move将packaged_task对象移动到新线程t中并传递了参数3和4。新线程启动后会执行packaged_task关联的myFunction函数。主线程可以继续执行其他操作最后通过result.get()获取异步任务的结果。处理异常情况如果packaged_task关联的可调用对象在执行过程中抛出了异常这个异常会被捕获并存储在std::future对象中。当调用std::future的get()方法时异常会被重新抛出。#includeiostream#includefuture#includestdexceptintmyFunction(inta){if(a0){throwstd::invalid_argument(Input must be non - negative);}returna*a;}intmain(){std::packaged_taskint(int)task(myFunction);std::futureintresulttask.get_future();std::threadt(std::move(task),-5);t.detach();try{intsquareresult.get();std::coutThe square is: squarestd::endl;}catch(conststd::invalid_argumente){std::cerrException caught: e.what()std::endl;}return0;}在上述代码中myFunction函数在输入参数为负数时会抛出std::invalid_argument异常。当新线程执行packaged_task关联的myFunction函数并抛出异常后主线程调用result.get()时会捕获到这个异常并进行相应的处理。总结packaged_task为C中的异步任务处理提供了一种灵活的方式。通过将可调用对象与std::future关联起来我们可以方便地实现任务的封装、异步执行和结果获取。在实际编程中可以根据具体的需求选择在当前线程中直接调用packaged_task对象或者将其移动到新线程中实现异步处理。同时要注意处理可调用对象可能抛出的异常以确保程序的健壮性。

更多文章