2009-06-16 25 views
27

是否有任何方法将Boost.Asio与Qt4(首选)或GTK主循环集成? GTK提供了像API这样的poll(2),所以技术上应该是可能的。 Qt提供了自己的网络层,但我更愿意使用为Boost.Asio编写的现有代码。 我想使用其他线程将它们整合到而不使用如何将Boost.Asio主循环集成到GUI框架(如Qt4或GTK)中

是否有任何参考如何为Qt4(首选)或GTKmm做到这一点?

谢谢。

编辑

我想clearify几件事,使答案更容易。 Qt和gtkmm的提供 “选择像” 功能:

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

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

+0

这里有一个很好的解决方案的任何更新?我刚刚遇到同样的问题... – Macke 2009-10-05 21:07:09

回答

8

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

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

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

就会造成,即io_service对象正在连同Qt应用程序运行在一个线程无需额外延迟和性能下降(如在调用io_service对象::民意调查()“不时”的解决方案)。

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

6

如果我正确理解你的问题,你有代码写为Boost.Asio。您想在GUI应用程序中使用该代码。

在你的问题中有什么不明确的是,如果你想通过asynio包装Qt/Gtk网络层来让你的代码工作,如果你只是寻找一个同时具有gui事件循环和asynio的解决方案。

我会承担第二种情况。

Qt和Gtk都有方法在事件循环中集成外部事件。请参阅例如qtgtk其中Qt事件循环插入到Gtk中。

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

在升压快看ASIO后,我认为你需要做到以下几点:

  • 会定期QTimer具有持续时间的零调用io_service对象:: run()的所有的时间。这样,一旦异步操作完成,boost :: asio就会调用你的完成处理程序。
  • 在你完成处理,有两个选项:
    • 如果你完成操作是漫长的,从GUI中分离,做您的业务,并确保调用qApp。processEvents()经常保持敏感
    • 的GUI,如果你只是想GUI来传送回:
      1. 定义自定义QEvent
      2. subscribe to this event
      3. 使用QCoreApplication::postEvent()发布自己的活动,Qt的事件循环。
+2

您建议的解决方案需要某种忙或短暂的等待,这是不理想的。我宁愿合并两个循环,而不是运行-qt/run-asio/run-qt/run-asio,尤其是当我等待来自网络的用户输入/输入可能同时出现时。 – Artyom 2009-06-19 12:05:58

+1

没有免费的午餐。如果我理解正确,asio有一个必要的部分,它调用:: run()函数,它是阻塞的。如果该功能被阻止,您可以从后台线程中调用该功能,否则可能会阻止您的应用程序。 你提到事件循环集成,但从快速浏览,我没有发现任何事件循环在asio中。异步调用不一定要使用事件循环。 – 2009-06-19 15:17:38

+0

你也可以这样做:对所有东西都使用Qt,只是将qt网络事件“转换”为asio预期的格式。通过这种方式,您不会使用asio,但必须在与之前相同的asio中调用遗留代码。 – 2009-06-19 15:21:08

15

简单: 建立一个QT插槽调用io_service::poll_one()属于GUI。将该插槽连接到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()。这将导致任何挂起的Asio完成处理程序从gui线程被调用。由于处理程序正在gui线程中运行,因此它们可以自由修改小部件。

现在您需要确保io_service有机会定期运行。我建议几次重复gui信号调用poll_one()。我相信QT有一个诀窍信号可以做到这一点。您当然可以推出自己的QT信号以获得更多控制权。

2

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

在单独的线程上运行io_service :: run()可能是最好的选择。

相关问题