Comment intégrer la boucle principale de Boost.Asio dans une infrastructure graphique telle que Qt4 ou GTK

StackOverflow https://stackoverflow.com/questions/1001032

Question

Existe-t-il un moyen d’intégrer Boost.Asio à la boucle principale Qt4 (recommandée) ou GTK? GTK fournit un poll (2) comme une API, donc techniquement, cela devrait être possible. Qt fournit sa propre couche réseau, mais je préfère utiliser le code existant écrit pour Boost.Asio. Je souhaite les intégrer sans utiliser un thread supplémentaire.

Existe-t-il une référence à cette opération pour Qt4 (préféré) ou GTKmm?

Merci.

Modifier

Je veux clarifier plusieurs choses pour faciliter la réponse. Qt et GTKmm fournissent tous deux " choisissez comme " fonctionnalité:

La question est donc de savoir comment intégrer les "sélecteurs / sondeurs" existants. comme réacteur à Boost.Asio io_service . Aujourd'hui, Boost.Asio peut utiliser select, kqueue, epoll, / dev / poll et iocp en tant que service réacteur / réactif. Je souhaite l'intégrer à la boucle principale du cadre de l'interface graphique.

Toutes les suggestions et solutions (meilleures) sont les bienvenues.

Était-ce utile?

La solution

C'est une question plutôt ancienne, mais pour ceux qui la lisent maintenant, j'aimerais partager mon code , qui est une implémentation de QAbstractEventDispatcher. pour boost :: asio.

Tout ce dont vous avez besoin est d'ajouter la ligne suivante avant de créer QApplication (généralement dans main ()).

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

Cela provoquera l'exécution d'io_service avec l'application qt dans un thread sans perte de latence ni de performances supplémentaires (comme dans la solution avec l'appel de io_service :: poll () "de temps en temps").

Malheureusement, ma solution concerne uniquement les systèmes posix, car elle utilise asio :: posix :: stream_descriptor. Le support Windows peut nécessiter une approche complètement différente ou très similaire - je ne sais pas vraiment.

Autres conseils

Simple: Construisez un emplacement QT qui appelle le io_service :: poll_one () appartenant à l'interface graphique. Connectez cet emplacement au signal tick de QT.

En profondeur: Heureusement pour vous Boost.Asio est très bien conçu. Il existe de nombreuses options sur la façon de fournir un thread d'exécution aux internes asynchrones sous-jacents. Les gens ont déjà mentionné l'utilisation de io_service :: run () , un appel bloquant présentant de nombreux inconvénients.

Vous n'êtes autorisé à accéder aux widgets d'interface graphique qu'à partir d'un seul thread. Les threads externes ont généralement besoin de publier des événements sur l'interface graphique s'ils souhaitent muter n'importe quel widget. Ceci est très similaire à la façon dont fonctionne Asio.

L’approche naïve consiste à dédier un seul thread (ou minuteur) à l’exécution de io_service :: run () et à ce que le gestionnaire d’achèvement Asio envoie un signal gui. Cela fonctionnera .

À la place, vous pouvez utiliser la garantie que les gestionnaires d'achèvement ne seront appelés que dans le fil d'exécution de l'appelant io_service . N'avez pas l'appel de fil de l'interface graphique io_service :: run () car il bloque et pourrait suspendre l'interface graphique. A la place, utilisez io_service :: poll () ou io_service :: poll_one () . Ainsi, tous les gestionnaires d'achèvement Asio en attente seront appelés à partir du thread gui. Étant donné que les gestionnaires s'exécutent dans le fil du gui, ils sont libres de modifier les widgets.

Vous devez maintenant vous assurer que io_service a la possibilité de s'exécuter régulièrement. Je recommande d’avoir plusieurs fois un appel de signal gui répétitif poll_one () . Je crois que QT a un signal de tick qui ferait l'affaire. Vous pouvez bien sûr utiliser votre propre signal QT pour plus de contrôle.

Si je comprends bien votre question, vous avez un code écrit pour Boost.Asio. Vous souhaitez utiliser ce code dans une application graphique.

Ce qui n’est pas clair dans votre question est de savoir si vous souhaitez encapsuler les couches réseau Qt / Gtk en mode asynchrone pour que votre code fonctionne, si vous recherchez simplement une solution permettant de combiner une boucle d’événement gui et un asynchrone.

Je vais assumer le deuxième cas.

Qt et Gtk ont ??tous deux des méthodes pour intégrer des événements étrangers dans leur boucle d’événements. Voir par exemple qtgtk où la boucle d'événements Qt est connectée à Gtk.

Dans le cas spécifique de Qt, si vous souhaitez générer des événements pour Qt, vous pouvez utiliser la classe suivante: QAbstractEventDispatcher .

Après un coup d’œil sur boost asio, je pense que vous devez procéder comme suit:

  • a un QTimer récurrent de durée zéro qui appelle io_service :: run () tout le temps. Ainsi, boost :: asio appellera votre gestionnaire d'achèvement dès que votre opération asynchrone sera terminée.
  • dans votre gestionnaire d'achèvement, deux options:
    • si votre opération d'achèvement est longue, séparée de l'interface graphique, exercez votre activité et assurez-vous d'appeler régulièrement qApp.processEvents () pour que l'interface graphique reste active
    • si vous voulez simplement communiquer avec l'interface graphique:
      1. définir un type QEvent personnalisé
      2. vous abonner à cet événement
      3. publiez votre boucle d'événement sur Qt avec QCoreApplication :: postEvent ( ) .

L'intégration réelle des boucles principales est possible. C'est juste une grosse douleur (et je n'ai pas encore vraiment essayé).

Exécuter io_service :: run () sur un thread séparé est probablement la solution.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top