当使用预协程 asio 接口时,我可以在当前执行上下文(主函数)中调度一个异步函数,并让它在ctx.
#include <iostream>
#include <asio.hpp>
using namespace std;
using namespace literals;
int main() {
asio::io_context ctx;
asio::steady_timer t(ctx, 2s);
asio::dispatch([&](){
cout << "inside coro before wait" << endl;
t.async_wait([](asio::error_code){
cout << "inside coro after wait" << endl;
});
});
cout << "starting ctx.run()" << endl;
ctx.run();
}
Run Code Online (Sandbox Code Playgroud)
$ ./sol
inside coro before wait
starting ctx.run()
inside coro after wait
Run Code Online (Sandbox Code Playgroud)
我想用协程复制它,asio::awaitable但dispatch不支持协程。
另一方面,co_spawn仅将协程添加到上下文中,并且不会立即启动它。
我可以使用ctx.poll()/ctx.run_one()但协程必须是唯一准备执行的协程,或者至少是第一个协程。
答案
如果我没有弄错的话,启动协程(从协程外部)的唯一方法是使用asio::co_spawn(executor, awaitable, token). 与 相比dispatch,co_spawn接受一个 executor 作为参数,正如 @sehe 所说,dispatch使用关联的 executor。因此,要回答我关于如何立即启动协程的问题,就是在 中运行它asio::system_executor()。
$ ./sol
inside coro before wait
starting ctx.run()
inside coro after wait
Run Code Online (Sandbox Code Playgroud)
$ ./sol
inside coro before wait
starting ctx.run()
inside coro after wait
Run Code Online (Sandbox Code Playgroud)
该代码有多种方式无法执行其建议/您描述的操作:
asio::dispatch([](){
// executes immediately
asio::steady_timer t(ctx, 2s);
t.async_wait([](){
// executes in ctx.run()
});
});
ctx.run();
Run Code Online (Sandbox Code Playgroud)
它永远不会等待2秒,因为t的析构函数在启动后会async_await 立即取消。
ctx显然是静态的或全局的,因为它没有被捕获
完成处理程序没有所需的签名
即使它正确地接受了一个error_code变量,它也不会“ 在 ctx.run() 中执行[s]”,因为在lambda 的关联执行器dispatch上进行分派。由于没有其他关联,因此将默认为 的默认构造实例。asio::system_executor
问: 另一方面,asio::co_spawn 仅将协程添加到上下文中,并且不会立即启动它。
我认为这也不准确。正如您提到的,您给出的代码无效(因为post不支持协程)。当固定使用时co_spawn,我们可以显示它在里面运行ctx.run():
#include <boost/asio.hpp>
#include <iostream>
namespace asio = boost::asio;
using namespace std::chrono_literals;
int main() {
asio::io_context ctx;
asio::co_spawn(
ctx,
[]() -> asio::awaitable<void> {
auto ex = co_await asio::this_coro::executor;
asio::steady_timer t(ex, 2s);
co_await t.async_wait(asio::use_awaitable);
std::cout << "inside ctx.run()" << std::endl;
// co_return;
},
asio::detached);
std::cout << "before ctx.run()" << std::endl;
ctx.run();
std::cout << "after ctx.run()" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
印刷
我真的认为99%的问题都取决于这些错误的前提,所以我会在阐述之前等待你的反应。
想得更久,我想你可能会对这个问题有不同的看法:asio How to change the executor inside an waiting? ,但没有意识到您无意中使用了系统上下文进行调度。
下面是(关联的)执行器如何与协程简历交互的更全面的说明:全尺寸
另请注意,当工作仅在系统上下文中挂起时,如何需要工作防护来避免 ctx 耗尽工作。
我强烈建议不要依赖系统上下文,但是这个插图应该可以帮助您连接所有点?