首页 > 其他分享 >std::promise 和 std::packaged_task

std::promise 和 std::packaged_task

时间:2025-01-14 20:55:26浏览次数:1  
标签:std 异步 task get packaged future

std::promisestd::packaged_task 都是 C++11 标准库中用于管理异步操作的工具,它们都允许你通过 std::future 获取异步操作的结果。然而,它们在设计目的和使用场景上有显著的区别。以下是对两者的详细比较:

std::promise

主要用途

  • 手动设置结果:std::promise 提供了一种机制来手动设置异步操作的结果或异常,并通过关联的 std::future 对象获取该结果。
  • 灵活控制:适用于需要显式控制何时以及如何设置结果的场景。

常用方法

  • set_value():设置共享状态的结果(适用于返回值类型)。
void set_value(const T& value); // 或者
void set_value(T&& value);

  set_exception():设置共享状态的异常信息。

void set_exception(std::exception_ptr p);

get_future():返回一个与当前 std::promise 关联的 std::future 对象。

std::future<T> get_future();
#include <iostream>
#include <future>
#include <thread>

void producer(std::promise<int> prom) {
    try {
        int result = 42; // 计算结果
        prom.set_value(result); // 设置共享状态的值
    } catch (...) {
        prom.set_exception(std::current_exception()); // 设置异常
    }
}

int main() {
    std::promise<int> prom;
    std::future<int> fut = prom.get_future(); // 获取与 promise 关联的 future

    std::thread t(producer, std::move(prom)); // 启动新线程执行生产者任务

    try {
        int value = fut.get(); // 阻塞直到共享状态就绪
        std::cout << "Promise returned: " << value << "\n";
    } catch (const std::exception& e) {
        std::cerr << "Exception caught: " << e.what() << "\n";
    }

    t.join(); // 等待线程结束
    return 0;
}

 

std::packaged_task

主要用途

  • 包装可调用对象:std::packaged_task 将任何可调用对象(如函数、lambda 表达式或函数对象)包装成一个异步任务,并返回一个 std::future 对象来获取该任务的结果。
  • 自动设置结果:任务执行完成后,std::packaged_task 自动设置结果或异常到关联的 std::future 对象。

常用方法

构造函数:接受一个可调用对象并包装它。

template< class Function >
explicit packaged_task( Function&& f );

operator():调用被包装的任务。

void operator()( Args... args );

get_future():返回一个与当前 std::packaged_task 关联的 std::future 对象。

get_future():返回一个与当前 std::packaged_task 关联的 std::future 对象。

 

#include <iostream>
#include <future>
#include <thread>

int task_function(int x) {
    return x * x;
}

int main() {
    std::packaged_task<int(int)> task(task_function); // 包装任务
    std::future<int> fut = task.get_future(); // 获取与 packaged_task 关联的 future

    std::thread t(std::move(task), 5); // 启动新线程执行任务

    int value = fut.get(); // 阻塞直到任务完成
    std::cout << "Packaged task returned: " << value << "\n";

    t.join(); // 等待线程结束
    return 0;
}

 

特性std::promisestd::packaged_task
主要用途 手动设置异步操作的结果或异常 包装可调用对象为异步任务,并自动设置结果或异常
灵活性 更灵活,适合需要显式控制何时及如何设置结果的场景 较少灵活性,但更方便直接执行可调用对象
设置结果的方式 使用 set_value() 和 set_exception() 自动设置结果或异常
获取 std::future 通过 get_future() 通过 get_future()
适用场景 当你需要在多个地方设置结果或处理复杂的异步逻辑时 当你需要简单地将一个函数或可调用对象包装为异步任务时

具体应用场景

  • std::promise

    • 当你需要在多个不同的地方设置异步操作的结果或异常时。
    • 当你需要手动控制何时以及如何设置结果时。
    • 在复杂的多线程环境中,可能需要在不同线程之间传递数据和状态时。
  • std::packaged_task

    • 当你有一个具体的可调用对象(如函数或 lambda 表达式),并且希望将其作为异步任务执行时。
    • 当你需要简化异步任务的创建和管理时,特别是当任务的结果可以直接从可调用对象中获得时。

      综合示例

      为了更好地理解两者的区别,下面是一个综合示例,展示了如何分别使用 std::promisestd::packaged_task 来实现相同的功能:

      #include <iostream>
      #include <future>
      #include <thread>
      
      void async_operation(std::promise<int> prom) {
          try {
              int result = 42; // 模拟异步操作
              prom.set_value(result);
          } catch (...) {
              prom.set_exception(std::current_exception());
          }
      }
      
      int main() {
          std::promise<int> prom;
          std::future<int> fut = prom.get_future();
      
          std::thread t(async_operation, std::move(prom));
      
          int value = fut.get();
          std::cout << "Promise returned: " << value << "\n";
      
          t.join();
          return 0;
      }

      使用 std::packaged_task

      #include <iostream>
      #include <future>
      #include <thread>
      
      int async_operation(int x) {
          return x * x; // 模拟异步操作
      }
      
      int main() {
          std::packaged_task<int(int)> task(async_operation);
          std::future<int> fut = task.get_future();
      
          std::thread t(std::move(task), 5);
      
          int value = fut.get();
          std::cout << "Packaged task returned: " << value << "\n";
      
          t.join();
          return 0;
      }

       

      总结

      • std::promise 提供了更高的灵活性,适合需要手动控制何时及如何设置异步操作结果的场景。
      • std::packaged_task 更加便捷,适合将一个具体的可调用对象包装为异步任务,并自动管理其结果或异常。

      根据具体的需求选择合适的工具可以提高代码的可读性和维护性。



标签:std,异步,task,get,packaged,future
From: https://www.cnblogs.com/zhoug2020/p/18671579

相关文章

  • 手机端rustdesk如何进行配置
    安装rustdesk客户端以后,可以按照下图填写配置信息手机版也是可以快速导入导出,可以方便从其他设备或者客户端直接导入配置信息,然后在本软件进行导入或者导出......
  • rustdesk如何开启远程教程
    手机端在软件底部选择【共享屏幕】,在共享屏幕里面选择启动服务。主控和被控手机同时都配置好了ID服务器的信息以后,在软件底部选择【连接】然后输入远程ID,选择连接就行了。提示输入密码,可以查看一下被控客户端的密码,或者可以给被控客户端设置固定密码。......
  • swoole Task用法示例
    <?php$server=newSwoole\Server('127.0.0.1',9501);$server->set(['worker_num'=>2,//worker进程数'task_worker_num'=>2,//Taskworker进程数]);$server->on('receive',function($server,$fd,$......
  • 【C++17 library features】深入解析 C++17 标准库中的文件系统 (std::filesystem)
    目录标题第一章:std::filesystem概述1.1C++17引入文件系统库的背景和动机1.2std::filesystem的主要功能和模块结构1.2.1路径管理(PathManagement)1.2.2文件和目录操作(FileandDirectoryOperations)1.2.3文件属性与状态(FileAttributesandStatus)1.2.4错误处理......
  • Towards Better Multi-task Learning: A Framework for Optimizing Dataset Combinati
    本文是LLM系列文章,针对《TowardsBetterMulti-taskLearning:AFrameworkforOptimizingDatasetCombinationsinLargeLanguageModels》的翻译。迈向更好的多任务学习:一个优化大型语言模型中数据集组合的框架摘要1引言2相关工作3框架4实验设置5结果6......
  • std::condition_variable
    std::condition_variable是C++11标准库中提供的一个同步原语,用于线程间的条件等待和通知机制。它允许一个或多个线程等待某个条件变为真(即被满足),并通过另一个线程的通知来唤醒这些等待的线程。主要特点条件等待:线程可以等待某个条件变量,直到其他线程通知该条件已被满足。通......
  • std::type_index 支持 std::Vector么
    std::type_index本身并不直接支持std::vector或其他具体类型的容器,但它可以用来表示和比较任何类型的类型信息,包括std::vector。你可以使用std::type_index来获取和比较std::vector的类型信息。获取 std::vector 的 std::type_index要获取一个std::vector的std::t......
  • Task实战
    一:场景描述在一个文件下查找js文件中指定的关键字,并记录完成查找所需时间。完成此任务使用了3种写法,分别为:1.仅使用一个task,在任务中进行for循环,循环调用异步业务处理方法,只利用一个后台线程进行业务处理。2.先查找出文件路径,然后对每一个文件路径创建一个task,然后用这N个task并......
  • wx.requestDeviceVoIP
    wx.requestDeviceVoIP(Objectobject)基础库2.27.3开始支持,低版本需做兼容处理。以Promise风格调用:不支持小程序插件:不支持微信鸿蒙OS版:支持相关文档:小程序音视频通话(for硬件)功能描述请求用户授权与设备(组)间进行音视频通话。参数Objectobject属性......
  • 安卓编译报错Execution failed for task ‘:expo-modules-core:prepareBoost‘. Not i
    作者:Kovli重要通知:红宝书第5版2024年12月1日出炉了,感兴趣的可以去看看,https://u.jd.com/saQw1vP红宝书第五版中文版红宝书第五版英文原版pdf下载(访问密码:9696)报错如下[RUN_GRADLEW]Executionfailedfortask':expo-modules-core:prepareBoost'.[RUN_GRADLEW]>Cou......