co_spawn 如何与 co_await 一起使用?

问题描述 投票:0回答:1

我目前正在

task_sub()
函数的开头创建多个
task_main()
,并等待这些
task_sub()
结束后再退出
task_main()
。只有一个线程。我该怎么办?

有什么办法可以达到这个要求吗?注意:

task_main()
task_sub()
不在同一级别,
task_sub()
必须在
task_main()
中创建。

asio 1.31.0


awaitable<void> task_sub()
{
    // TODO something
}

awaitable<void> task_main()
{
    printf("task_main begin\n");
    
    // create some task_sub and execute
    auto task1 = co_spawn(co_await this_coro::executor, task_sub(), xxxxxx?);
    auto task2 = co_spawn(co_await this_coro::executor, task_sub(), xxxxxx?);

    // main loop
    // TODO something

    // waiting task
    co_await task1;
    co_await task2;

    printf("task_main end\n");
}

我尝试过使用

use_future
等待任务结束,但它不支持
co_await
并且
task1.wait()
是同步和阻塞的,这会阻塞主循环。

awaitable<void> task_main()
{
    printf("task_main begin\n");

    // create some task_sub and execute
    //
    std::future<void> task1 = co_spawn(co_await this_coro::executor, task_sub(), use_future);
    std::future<void> task2 = co_spawn(co_await this_coro::executor, task_sub(), use_future);

    // main loop
    // TODO something

    // waiting task
    //co_await task1;
    //co_await task2;

    //is blocked
    task1.wait();
    task2.wait();

    printf("task_main end\n");
}

我也尝试过使用

channel
,可以用,但是不太漂亮


//...
#include <asio/experimental/channel.hpp>

using exit_channel = asio::experimental::channel<void(asio::error_code)>;

awaitable<void> task_sub(exit_channel& channel)
{
    // TODO something

    //end
    co_await channel.async_send(error_code{});
}

awaitable<void> task_main()
{
    printf("task_main begin\n");

    auto ctx = co_await this_coro::executor;

    // create some task_sub and execute
    exit_channel task1_channel(ctx, 1);
    exit_channel task2_channel(ctx, 1);
    co_spawn(ctx, task_sub(task1_channel), detached);
    co_spawn(ctx, task_sub(task2_channel), detached);

    // main loop
    // TODO something

    // waiting task
    co_await task1_channel.async_receive();
    co_await task2_channel.async_receive();

    printf("task_main end\n");
}

而且

co_spawn(,,use_awaitable)
,它不会在
co_spawn
开始执行,所以这不是你想要的。

boost-asio
1个回答
0
投票

就像我之前回答您删除的问题一样,您可以使用

use_promise

在 Coliru 上生活¹

#include <asio.hpp>
#include <asio/experimental/promise.hpp>
#include <asio/experimental/use_promise.hpp>
#include <stdio.h>
using asio::awaitable;
using asio::experimental::use_promise;
using namespace std::chrono_literals;
namespace this_coro = asio::this_coro;

awaitable<void> delay(auto dur) {
    co_await asio::steady_timer{co_await this_coro::executor, dur}.async_wait();
}

awaitable<void> task_sub(char const* caption, int n, auto ival) {
    for (int i = 0; i < n; ++i) {
        printf("task_sub '%s' %d\n", caption, i);
        co_await delay(ival);
    }
}

awaitable<void> task_main()
{
    printf("task_main begin\n");
    
    auto ex = co_await this_coro::executor;
    // create some task_sub and execute
    auto task1 = co_spawn(ex, task_sub("task1", 5, 500ms), use_promise);
    auto task2 = co_spawn(ex, task_sub("task2", 4, 750ms), use_promise);

    // main loop
    // TODO something
    co_await task_sub("task_main", 3, 1000ms);

    printf("task_main wait\n");

    co_await std::move(task1);
    co_await std::move(task2);

    printf("task_main end\n");
}

int main() {
    asio::io_context ctx;
    co_spawn(ctx, task_main(), asio::detached);
    ctx.run();
}

观看直播:

¹ 在线使用 Boost Asio,因为它没有独立的 Asio

© www.soinside.com 2019 - 2024. All rights reserved.