2009-06-16 59 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()可能是最好的選擇。

相關問題