[英]Interrupt boost::asio synchronous read?
我正在使用asio同步套接字从后台线程通过TCP读取数据。 这封装在“服务器”类中。
但是,我希望线程在调用此类的析构函数时退出。 问题是对任何读取函数的调用都会阻塞,因此线程不能轻易终止。 在Win32中有一个API: WaitForMultipleObjects
,它将完全符合我的要求。
如何通过提升获得类似的效果?
在我们的应用程序中,我们设置“终止”条件,然后使用自连接到线程正在侦听的端口,以便它唤醒,注意终止条件并终止。
您还可以检查boost实现 - 如果它们只对套接字进行简单读取(即,不在内部使用WaitForMultipleObjects之类的东西),那么您可能会得出结论,没有任何东西可以简单而干净地解除阻塞。 如果他们在等待多个对象(或完成端口),你可以挖掘周围以查看唤醒阻塞线程的能力是否暴露在外面。
最后,你可以杀死线程 - 但你必须超出提升才能做到这一点,并了解后果,例如悬空或泄漏的资源。 如果您正在关闭,这可能不是一个问题,取决于该线程正在做什么。
我发现没有简单的方法可以做到这一点。 据说,有办法取消win32 IOCP,但它在Windows XP上运行不佳。 MS确实为Windows Vista和7修复了它。取消asio async_read
或async_write
的推荐方法是关闭套接字。
[析构函数]等待完成处理程序
[完成]如果拆除并且我们因套接字关闭而失败,通知析构函数完成处理程序已完成。
如果您选择实施此操作,请务必小心。 关闭套接字非常简单。 “等待完成处理程序”然而却是巨大的不足。 当服务器的线程及其析构函数交互时,可能会出现一些细微的角落情况和竞争条件。
这非常微妙,我们构建了一个完成包装器(类似于io_service::strand
只是为了同步取消所有挂起的完成回调。
最好的方法是创建一个socketpair()
,(无论是在boost::asio
用语中),将读取器端添加到事件循环中,然后关闭socketpair()
器端。 您将立即在该套接字上使用eof事件唤醒。
然后线程必须自愿关闭自己。
线程的产生者应该在它的析构函数中,具有以下内容:
~object()
{
shutdown_queue.shutdown(); // ask thread to shut down
thread.join(); // wait until it does
}
boost::system::error_code _error_code;
client_socket_->shutdown(client_socket_->shutdown_both, _error_code);
上面的代码帮助我立即关闭同步读取。
使用socket.cancel(); 结束在套接字上阻塞的所有当前异步操作。 客户端套接字可能需要在循环中被杀死。 我从来没有以这种方式关闭服务器,但你可以使用shared_from_this()并在循环中运行cancel()/ close(),类似于boost聊天示例async_writes到所有客户端的方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.