C++ boost::asio在使用post()时没有调用处理程序,在直接调用函数时有效(io_上下文有效)

C++ boost::asio在使用post()时没有调用处理程序,在直接调用函数时有效(io_上下文有效),c++,boost-asio,future,boost-thread,C++,Boost Asio,Future,Boost Thread,我试图通过使用计时器定期触发从应用程序到服务器的请求。被调用的函数通过使用boost::promise等待完成(如果手动调用,需要显示成功状态)。启动时,我直接调用该函数,它会顺利完成。然后计时器会周期性地再次调用它,但当通过最后期限计时器启动时,承诺永远不会实现 通过.post()调用时,将打开与服务器的连接,但在客户端,永远不会触发句柄\连接处理程序。io_上下文已分配工作 我已经尝试将承诺移动到ServiceRequest类,而不是传递引用,并将其作为类成员实现,以排除生命周期问题 我已将

我试图通过使用计时器定期触发从应用程序到服务器的请求。被调用的函数通过使用boost::promise等待完成(如果手动调用,需要显示成功状态)。启动时,我直接调用该函数,它会顺利完成。然后计时器会周期性地再次调用它,但当通过最后期限计时器启动时,承诺永远不会实现

通过.post()调用时,将打开与服务器的连接,但在客户端,永远不会触发句柄\连接处理程序。io_上下文已分配工作

我已经尝试将承诺移动到ServiceRequest类,而不是传递引用,并将其作为类成员实现,以排除生命周期问题

我已将整个问题简化为失败代码的最小示例:

(Coliru上的演示:,)

class-ServiceRequest:public boost::从\u中启用\u共享\u
{
公众:
ServiceRequest(boost::asio::io_服务和io_服务、客户端和客户端、boost::promise和promise)
:io_服务(io_服务),
插座(io)(服务)),,
客户(客户),,
允诺
{}
~ServiceRequest()
{}
void Start()
{
套接字异步连接(
boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(“127.0.0.1”),3005),
boost::bind(&ServiceRequest::handle\u connect,
从_this()共享了_,
boost::asio::占位符::错误
)
);
}
私人:
无效句柄连接(const boost::system::error\u code&ec)
{
如果(!ec)
{
承诺设置值(真);
boost::asio::异步写入(套接字),
boost::asio::buffer(“测试”),
boost::绑定(&ServiceRequest::关闭_套接字,
共享\u来自\u this())
);              
}
其他的
{           
承诺设置值(假);
}           
}
void close_socket()
{
套接字关闭(boost::asio::ip::tcp::socket::shutdown\u两者);
插座关闭();
}
boost::asio::io_服务和io_服务;
boost::asio::ip::tcp::socket;
客户&客户;
boost::promise&promise;
};
类请求处理程序
{
公众:
RequestHandler(boost::asio::io_服务和io_服务、客户端和客户端)
:io_服务(io_服务),
客户(客户)
{}
~RequestHandler()
{}
bool请求服务()
{
承诺;承诺;
boost::shared\u ptr service\u request=boost::make\u shared(io\u service\uuuuuuuuu,client\uuuu,promise);
服务请求->启动();
bool result=promise.get_future().get();
返回结果;
}
私人:
boost::asio::io_服务和io_服务;
客户&客户;
};
类客户端{
公众:
客户()
:io_service_uu(),
工作(io)和服务,
线程组,
计时器(io_服务_),
请求\u处理程序\u(io\u服务\u,*此)
{
线程组创建线程(boost::bind(&boost::asio::io_服务::run,&io_服务));
}
~Client()
{
io_服务_u.stop();
thread_group_u.join_all();
}
void RequestService()
{

io_service_uuu.post(boost::bind(&RequestHandler::RequestService,&request_handler_uuu));//您只有一个线程在调用
io_service::run

post()
在io_服务的一个线程上执行您从io_服务中为其提供的函数。您试图在io_服务的主循环中运行的函数(
RequestHandler::RequestService
)是一个阻塞函数,正在等待io_服务线程上执行的工作实现承诺。这将永远不会完成,因为您已阻塞io_服务线程


这是使用ASIO或任何异步框架时需要避免的主要错误之一。千万不要在处理事件的线程中阻塞,因为您可能会引入微妙的(或不太微妙的)像这样的死锁。

谢谢你的回答。现在我觉得有点傻,因为我应该知道这一点。我想我没有看到所有树的森林,因为我试图避免多线程(复杂的原因,简短的解释:现有的代码库,目前正在重构,不是线程安全的,目标是达到目标)现在,我将所有调度/计时器放在第二个线程中,操作结果通过回调函数发送给调用者。呵呵,没问题。我发现使用回调是处理异步结果的一种很好的最小公分母方法。它为您提供了链接另一个异步请求或将结果填充到pr中的选项省略其他线程正在等待的消息。
@asio|1559149650.446538|0*1|socket@00000000007b9d40.async_connect
@asio|1559149650.456538|>1|ec=system:0
@asio|1559149650.456538|1*2|socket@00000000007b9d40.async_send
@asio|1559149650.456538|<1|
@asio|1559149650.456538|>2|ec=system:0,bytes_transferred=5
@asio|1559149650.456538|2|socket@00000000007b9d40.close
@asio|1559149650.456538|<2|
@asio|1559149477.071693|0*1|io_context@000000000022fd90.post
@asio|1559149477.071693|>1|
@asio|1559149477.071693|1*2|socket@00000000007b9e10.async_connect