如何在GUI框架中集成Boost.Asio主循环,如Qt4或GTK

时间:2009-06-16 11:57:48

标签: qt4 gtk boost-asio event-loop

有没有办法将Boost.Asio与Qt4(首选)或GTK主循环集成? GTK像API一样提供poll(2),因此技术上应该是可行的。 Qt提供了自己的网络层,但我更喜欢使用为Boost.Asio编写的现有代码。 我希望使用其他线程将集成在一起。

是否有任何参考如何为Qt4(首选)或GTKmm?

执行此操作

感谢。

修改

我想澄清几件事情,让答案更轻松。 Qt和GTKmm都提供 “选择喜欢”功能:

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

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

4 个答案:

答案 0 :(得分:15)

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

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

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

天真的方法是将一个线程(或计时器)专用于运行io_service::run()并让Asio完成处理程序发布一个gui信号。 工作。

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

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

答案 1 :(得分:9)

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

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

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

这将导致io_service与qt应用程序一起在一个线程中运行而没有额外的延迟和性能下降(就像在不时调用io_service :: poll()的解决方案中那样)。

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

答案 2 :(得分:6)

如果我正确理解您的问题,您可以为Boost.Asio编写代码。您希望在GUI应用程序中使用该代码。

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

我将假设第二种情况。

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

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

快速浏览一下boost asio后,我认为你需要做以下事情:

  • 有一个持续时间为零的重复QTimer,它一直调用io_service :: run()。这样,一旦异步操作完成,boost :: asio就会调用你的完成处理程序。
  • 在您的完成处理程序中,有两个选项:
    • 如果您的完成操作很长,与GUI分开,请执行您的业务并确保定期调用qApp.processEvents()以保持GUI响应
    • 如果您只是想与gui沟通:
      1. 定义自定义QEvent类型
      2. subscribe to this event
      3. 使用QCoreApplication::postEvent()将您的活动发布到Qt事件循环。

答案 3 :(得分:2)

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

在单独的线程上运行io_service :: run()可能就是这样。