C++ Boost.Asio 入门 之 多任务

C++ Boost.Asio 入门 之 多任务

上一节我们使用下面的代码完成了Hello World.这是完全异步的代码.

static awaitable<std::string> async_print(const std::string message){
    std::cout << "message1: " << message << "\n";
    auto executor = co_await boost::asio::this_coro::executor;
    std::cout << "message2: " << message << "\n";
    boost::asio::steady_timer timer(executor);
    timer.expires_after(std::chrono::seconds(1));
    std::cout << "message3: " << message << "\n";
    co_await timer.async_wait(boost::asio::use_awaitable);
    std::cout << "message4: " << message << "\n";
    co_return "Hello World Coroutine!";
}

void learn04(){
    boost::asio::io_context ioContext(1);
    auto result = boost::asio::co_spawn(ioContext, async_print("Hello World From Coroutine!"), boost::asio::use_future);
    ioContext.run();
    std::cout << result.get() << "\n";
}

执行下面代码体验1个线程执行多个协程的效率

static boost::asio::awaitable<std::string> async_print(const std::string message){
	std::cout << "message1: " << message << "\n";
	auto executor = co_await boost::asio::this_coro::executor;
	std::cout << "message2: " << message << "\n";
	boost::asio::steady_timer timer(executor);
	timer.expires_after(std::chrono::seconds(1));
	std::cout << "message3: " << message << "\n";
	co_await timer.async_wait(boost::asio::use_awaitable);
	std::cout << "message4: " << message << "\n";
	const auto threadId = std::this_thread::get_id();
	std::cout << "threadId: " << threadId << "\n";
	co_return "Hello World Coroutine!";
}
void learn02(){
	std::cout << "hello World02n\n";
	boost::asio::io_context ioContext(1);
	std::vector<std::future<std::string>> results;
	constexpr u_int N = 10000;
	for(u_int i = 0; i < N; i ++ ){
		results.emplace_back(boost::asio::co_spawn(ioContext, async_print("Hello World From Coroutine!"), boost::asio::use_future));
	}
	ioContext.run();
	for(u_int i = 0; i < N; i ++ ){
		std::cout << "result i: " << i << ", value: " << results[i].get() << "\n";
	}
}

本节我们来看下如何使用Boost.Asio来进行多任务编程。

线程池 + 协程

static awaitable<int> async_print(const int a, const int b){
    auto threadId = std::this_thread::get_id();
    std::cout << "threadId: " << threadId << "\n";
    co_return a + b;
}
static constexpr u_int N = 100;
void learn04(){
    auto cores = std::thread::hardware_concurrency();
    std::cout << "cores: " << cores << "\n"; 

    boost::asio::io_context ioContext;

    // 创建一个 work_guard 避免 io_context 过早退出
    auto work = boost::asio::make_work_guard(ioContext);

    // 启动线程池
    std::vector<std::thread> threads;
    for(unsigned i = 0; i < cores; ++i){
        threads.emplace_back([&](){ ioContext.run(); });
    }

    // 提交协程
    auto result1 = boost::asio::co_spawn(ioContext, async_print(1, 2), boost::asio::use_future);
    auto result2 = boost::asio::co_spawn(ioContext, async_print(3, 4), boost::asio::use_future);

    // 等待结果
    std::cout << result1.get() << "\n";
    std::cout << result2.get() << "\n";

    // 停止 io_context
    work.reset();
    for(auto& t : threads) t.join();
}

实现一个awaitable

// 用 asio::post 包装任意耗时操作
boost::asio::awaitable<int> my_async_task(int value) {
    auto exec = co_await boost::asio::this_coro::executor;
    // post 一个任务到 io_context
    co_await boost::asio::post(exec, boost::asio::use_awaitable);
    auto threadId = std::this_thread::get_id();
    // std::this_thread::sleep_for(std::chrono::microseconds(100));
    std::cout << "running in io_context thread threadId: " << threadId << "\n";
    std::this_thread::sleep_for(std::chrono::microseconds(100));
    co_return value * 2;
}
static awaitable<int> asyncReadFile(const std::string fileName){
    std::this_thread::sleep_for(std::chrono::microseconds(200));
    int result = co_await my_async_task(42);  // 自定义 Awaitable
    std::this_thread::sleep_for(std::chrono::microseconds(200));
    std::cout << "after co_await, result=" << result << "\n";
    std::this_thread::sleep_for(std::chrono::microseconds(200));
    co_return 1 + 2;
}
static constexpr u_int N = 10000;
void learn04(){
    auto cores = std::thread::hardware_concurrency();
    std::cout << "cores: " << cores << "\n"; 

    boost::asio::io_context ioContext;

    // 创建一个 work_guard 避免 io_context 过早退出
    auto work = boost::asio::make_work_guard(ioContext);

    // 启动线程池
    std::vector<std::thread> threads;
    for(unsigned i = 0; i < cores; ++i){
        threads.emplace_back([&](){ ioContext.run(); });
    }

    // 提交协程
    auto result1 = boost::asio::co_spawn(ioContext, asyncReadFile("D:/SoftWare/LanguageProjects/C++Projects/learn01/src/learn02/learn02.cpp"), boost::asio::use_future);
    std::this_thread::sleep_for(std::chrono::microseconds(100));
    auto result2 = boost::asio::co_spawn(ioContext, asyncReadFile("D:/SoftWare/LanguageProjects/C++Projects/learn01/src/learn01/learn01.cpp"), boost::asio::use_future);

    // 等待结果
    std::cout << result1.get() << "\n";
    std::this_thread::sleep_for(std::chrono::microseconds(100));
    std::cout << result2.get() << "\n";

    std::vector<std::future<int>> results;
    
    for(int i = 0; i < N; i ++ ){
        results.emplace_back(boost::asio::co_spawn(ioContext, asyncReadFile("D:/SoftWare/LanguageProjects/C++Projects/learn01/src/learn02/learn02.cpp"), boost::asio::use_future));
    }

    for(int i = 0; i < N; i ++ ){
        std::cout << "result: " << i << ": " <<  results[i].get() << "\n";
    }

    // 停止 io_context
    work.reset();
    for(auto& t : threads) t.join();
}

TODO 下周末继续分析,协程 搭配 Boost.Asio还真是爽呀!!!

TODO

  1. 异步 vs 同步
  2. 网络请求,复用请求
  3. 使用协程 开启 web 服务器
posted @ 2025-09-07 22:29  爱情丶眨眼而去  阅读(9)  评论(0)    收藏  举报