29

有没有办法将 Boost.Asio 与 Qt4(首选)或 GTK 主循环集成?GTK 提供 poll(2) 之类的 API,所以技术上应该是可行的。Qt 提供了自己的网络层,但我更喜欢使用为 Boost.Asio 编写的现有代码。我想在使用额外线程的情况下集成它们。

有没有参考如何为 Qt4(首选)或 GTKmm 执行此操作?

谢谢。

编辑

我想澄清几件事以使答案更容易。Qt 和 GTKmm 都提供“选择喜欢”功能:

所以,问题是,如何将现有的“选择器/轮询器”作为反应器集成到 Boost.Asio io_service。今天,Boost.Asio 可以使用 select、kqueue、epoll、/dev/poll 和 iocp 作为 reactor/proactor 服务。我想将它集成到 GUI 框架的主循环中。

欢迎任何建议和解决方案(更好)。

4

4 回答 4

17

简单: 构建一个调用io_service::poll_one()属于 gui 的 QT 插槽。将该插槽连接到 QT 的tick信号。

深入浅出: 幸运的是,Boost.Asio 设计得非常好。关于如何为底层异步内部提供执行线程有很多选择。人们已经提到 using io_service::run(),这是一个有很多缺点的阻塞调用。

您只能从单个线程访问 gui 小部件。如果外部线程想要改变任何小部件,通常需要将事件发布到 gui。这与 Asio 的工作方式非常相似。

天真的方法是只使用一个线程(或计时器)来运行io_service::run(),并让 Asio 完成处理程序发布一个 gui 信号。这起作用。

相反,您可以保证仅在调用者的执行线程中调用完成处理程序io_service。没有 gui 线程调用io_service::run(),因为它被阻塞并且可能挂起 gui。而是使用io_service::poll()or io_service::poll_one()。这将导致从 gui 线程调用任何挂起的 Asio 完成处理程序。由于处理程序在 gui 线程中运行,因此它们可以自由修改小部件。

现在您需要确保io_service有机会定期运行。我建议重复poll_one()几次 gui 信号调用。我相信 QT 有一个滴答信号可以解决问题。您当然可以滚动自己的 QT 信号以获得更多控制。

于 2009-12-21T18:58:19.100 回答
10

这是一个相当老的问题,但对于那些现在正在阅读它的人,我想分享我的代码,它是用于 boost::asio 的 QAbstractEventDispatcher 的实现。

您只需要在创建 QApplication 之前添加以下行(通常它在 main() 中)。

QApplication::setEventDispatcher(new QAsioEventDispatcher(my_io_service));

这将导致 io_service 与 qt 应用程序一起在一个线程中运行,而不会产生额外的延迟和性能下降(例如在“不时”调用 io_service::poll() 的解决方案中)。

不幸的是,我的解决方案仅适用于 posix 系统,因为它使用 asio::posix::stream_descriptor 。Windows 支持可能需要完全不同或非常相似的方法 - 我真的不知道。

于 2014-12-14T22:26:59.950 回答
6

如果我正确理解了您的问题,那么您已经为 Boost.Asio 编写了代码。您想在 GUI 应用程序中使用该代码。

您的问题中不清楚的是,如果您只是在寻找一种同时具有 gui 事件循环和 asynio 的解决方案,您是否想通过 asynio 包装 Qt/Gtk 网络层以使您的代码正常工作。

我将假设第二种情况。

Qt 和 Gtk 都有将外部事件集成到其事件循环中的方法。参见例如qtgtk,其中 Qt 事件循环被插入到 Gtk 中。

在 Qt 的特定情况下,如果要为 Qt 生成事件,可以使用以下类:QAbstractEventDispatcher

在快速浏览了 boost asio 之后,我认为您需要执行以下操作:

  • 有一个持续时间为零的循环 QTimer,它一直调用 io_service::run() 。这样,boost::asio 将在您的异步操作完成后立即调用您的完成处理程序。
  • 在您的完成处理程序中,有两个选项:
    • 如果您的完成操作很长,与 GUI 分开,请做好您的工作并确保定期调用 qApp.processEvents() 以保持 GUI 响应
    • 如果您只想与 gui 进行交流:
      1. 定义自定义QEvent类型
      2. 订阅此活动
      3. 使用QCoreApplication::postEvent()将您的事件发布到 Qt 事件循环。
于 2009-06-19T11:00:13.917 回答
2

真正集成主循环可能的。这只是一个很大的痛苦(我还没有真正尝试过)。

在单独的线程上运行 io_service::run() 可能是要走的路。

于 2009-12-23T04:18:26.013 回答