Como integrar o loop principal Boost.Asio no quadro GUI como Qt4 ou GTK
-
05-07-2019 - |
Pergunta
Existe alguma maneira de integrar Boost.Asio com Qt4 (preferencial) ou loop principal do GTK? GTK fornece poll (2) como API então tecnicamente é deve ser possível. Qt fornece sua própria camada de rede, no entanto eu prefiro usar código existente escrito para Boost.Asio. Eu quero integrá-los sem usando um thread adicional.
Existe alguma referência como fazer isso para Qt4 (preferencial) ou GTKmm?
Graças.
Editar
Eu quero clearify várias coisas para tornar a resposta mais fácil. Ambos Qt e GTKmm fornecer "Seleccionar como" funcionalidade:
- 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
Assim, a pergunta é, como integrar existentes "seletores / pollers" como reator
io_service
Boost.Asio. Hoje, Boost.Asio pode usar escolha, kqueue, epoll, / dev / enquete e iocp como serviço de reator / proactor. Eu quero integrá-lo à principal loop de quadro GUI.
Todas as sugestões e soluções (melhor) são bem vindas.
Solução
É questão bastante antigo, mas para aqueles que estão lendo isso agora eu gostaria de compartilhar minha código que é uma implementação de QAbstractEventDispatcher para boost :: asio.
Tudo que você precisa é adicionar a seguinte linha antes de criar QApplication (geralmente está em main ()).
QApplication::setEventDispatcher(new QAsioEventDispatcher(my_io_service));
Ele fará com que io_service está sendo executado em conjunto com a aplicação qt em um segmento sem latência adicional e queda de desempenho (como em solução com a chamada io_service :: poll () "de tempos em tempos").
Infelizmente, a minha solução é para POSIX sistemas apenas, uma vez que usar asio :: POSIX :: stream_descriptor. suporte do Windows podem precisar abordagem completamente diferente ou muito semelhantes -. Eu realmente não sei
Outras dicas
simples:
Construir um slot QT que chama a io_service::poll_one()
pertencente ao gui. Ligação que o slot de sinal tick
do QT.
Em Profundidade:
Felizmente para você Boost.Asio é muito bem desenhado. Há muitas opções sobre como fornecer um segmento de execução para os internos assíncronos subjacentes. As pessoas já têm mencionar usando io_service::run()
, uma chamada de bloqueio com muitas desvantagens.
Você só estão autorizados a widgets de acesso gui a partir de um único segmento. roscas externas geralmente precisam eventos pós à GUI, se eles querem fazer mutação qualquer widget. Isto é muito semelhante à forma como Asio funciona.
A abordagem ingênua é uma thread apenas dedicar (ou temporizador) para executar io_service::run()
e ter o manipulador de conclusão Asio postar um sinal gui. Este irá trabalho.
Em vez disso você pode usar a garantia de que os manipuladores de conclusão só será chamado no segmento de execução do chamador io_service
. Não tem o io_service::run()
chamada fio de gui como é o bloqueio e poderia pendurar o gui. Em vez disso use io_service::poll()
ou io_service::poll_one()
. Isso fará com que qualquer pendente manipuladores de conclusão Asio a ser chamado a partir do fio de gui. Desde os manipuladores estão funcionando no segmento gui eles estão livres para modificar os widgets.
Agora você precisa certificar-se o io_service
tem a chance de correr regularmente. Eu recomendo ter uma chamada de sinal gui repetindo poll_one()
algumas vezes. Acredito QT tem um sinal de carrapato que faria o truque. Você poderia rolar naturalmente o seu sinal QT própria para mais controle.
Se entendi sua pergunta corretamente, você tem código escrito para Boost.Asio. Você gostaria de usar esse código dentro de um aplicativo GUI.
O que não está claro na sua pergunta é se você quer envolver as camadas de rede Qt / Gtk através asynio para o seu código de trabalho, se você está apenas à procura de uma solução para ter tanto um ciclo de eventos gui e asynio juntos.
Vou assumir o segundo caso.
Ambos Qt e Gtk têm métodos para integrar eventos estrangeiros em seu ciclo de eventos. Ver, por exemplo qtgtk onde o ciclo de eventos Qt está conectado a Gtk.
No caso específico da Qt, se você quiser gerar eventos para Qt, você pode usar a seguinte classe: QAbstractEventDispatcher .
Depois de uma rápida olhada impulso asio, eu acho que você precisa fazer o seguinte:
- têm um QTimer recorrentes com duração zero que as chamadas io_service :: run () o tempo todo. Dessa forma, boost :: asio vai chamar seu manipulador de conclusão logo que a sua operação assíncrona for concluída.
- no seu manipulador de conclusão, duas opções:
- Se a sua operação conclusão é longa, separado do GUI, fazer o seu negócio e certifique-se de qApp.processEvents de chamada () regularmente para manter o GUI responsivo
- se você quiser apenas para se comunicar de volta com o gui:
- QEvent tipo costume
- subscrever este evento
- publicar seu evento para o Qt ciclo de eventos usando QCoreApplication :: postEvent ( ) .
Genuinamente integrando os principais laços é possível. É apenas uma grande dor (e eu ainda tenho que realmente tentar).
Running io_service :: run () em um segmento separado é provavelmente o caminho a percorrer.