Boost.AsioメインループをQt4やGTKなどのGUIフレームワークに統合する方法
-
05-07-2019 - |
質問
Boost.AsioをQt4(推奨)またはGTKメインループと統合する方法はありますか? GTKはAPIのようなpoll(2)を提供するため、技術的には可能です。 Qtは独自のネットワーク層を提供しますが、Boost.Asio用に作成された既存のコードを使用することを好みます。 追加のスレッドを使用せずにせずにそれらを統合したい。
Qt4(推奨)またはGTKmmでこれを行う方法についての参照はありますか?
ありがとう。
編集
答えを簡単にするために、いくつかのことを明確にしたいと思います。 QtとGTKmmの両方が提供します 「いいね」を選択機能:
- http://qt-project.org/doc/qt- 5.0 / qtcore / qsocketnotifier.html
- http://www.gtkmm.org/ docs / glibmm-2.4 / docs / reference / html / group__MainLoop.html
つまり、問題は、既存の「セレクター/ポーラー」を統合する方法です。リアクターとして
Boost.Asio io_service
。現在、Boost.Asioは、select、kqueue、epoll、/ dev / pollおよびiocpをリアクター/プロクターサービスとして使用できます。 GUIフレームワークのメインループに統合したい。
あらゆる提案と解決策(より良い)を歓迎します。
解決
やや古い質問ですが、今読んでいる人のために、 QAbstractEventDispatcherの実装である私のコードを共有したいと思います。 boost :: asioの場合。
必要なのは、QApplicationを作成する前に次の行を追加することだけです(通常はmain()にあります)。
QApplication::setEventDispatcher(new QAsioEventDispatcher(my_io_service));
これにより、io_serviceが1つのスレッドでqtアプリケーションと一緒に実行され、レイテンシーやパフォーマンスが低下することはなくなります(io_service :: poll()"から時々"を呼び出すソリューションのように)。
残念ながら、私のソリューションはposixシステムのみです。asio :: posix :: stream_descriptorを使用しているためです。 Windowsのサポートには、まったく異なるアプローチまたは非常に類似したアプローチが必要な場合があります-よくわかりません。
他のヒント
シンプル:
guiに属する io_service :: poll_one()
を呼び出すQTスロットを作成します。そのスロットをQTの tick
シグナルに接続します。
詳細:
幸いなことに、Boost.Asioは非常にうまく設計されています。基礎となる非同期内部に実行のスレッドを提供する方法には多くのオプションがあります。人々は、多くのデメリットを持つブロッキング呼び出しである io_service :: run()
の使用についてすでに言及しています。
単一のスレッドからのみguiウィジェットにアクセスできます。外部スレッドは通常、ウィジェットを変更したい場合、GUIにイベントをポストする必要があります。これは、Asioの動作に非常に似ています。
単純なアプローチは、1つのスレッド(またはタイマー)を 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シグナルをロールすることもできます。
私があなたの質問を正しく理解していれば、Boost.Asioのために書かれたコードを持っています。 GUIアプリケーション内でそのコードを使用したいと思います。
質問で明確でないのは、guiイベントループとasynioの両方を同時に使用するためのソリューションを探している場合に、コードが機能するようにasynioを介してQt / Gtkネットワークレイヤーをラップするかどうかです。
2番目のケースを想定します。
QtとGtkの両方には、外部イベントをイベントループに統合するメソッドがあります。たとえば、QtイベントループがGtkにプラグインされている qtgtk を参照してください。
Qtの特定のケースで、Qtのイベントを生成する場合、次のクラスを使用できます: QAbstractEventDispatcher 。
boost asioを簡単に確認した後、次のことを行う必要があると思います。
- io_service :: run()を常に呼び出す期間0のQTimerを繰り返し使用します。このように、boost :: asioは非同期操作が完了するとすぐに完了ハンドラーを呼び出します。
- 完了ハンドラには、2つのオプションがあります。
- 完了操作がGUIから分離された長い操作である場合は、ビジネスを行い、qApp.processEvents()を定期的に呼び出してGUIの応答性を維持してください
- GUIとやり取りしたい場合:
- カスタム QEvent タイプを定義
- このイベントに登録
- QCoreApplication :: postEvent( )。
メインループを完全に統合することは 可能です。それはただの大きな痛みです(そして、私はまだ実際に試していない)。
別のスレッドでio_service :: run()を実行するのがおそらく方法です。