Domanda

Esiste un modo per integrare Boost.Asio con Qt4 (preferito) o GTK main loop? GTK fornisce sondaggi (2) come API, quindi tecnicamente dovrebbe essere possibile. Qt fornisce il proprio livello di rete, tuttavia preferisco usare il codice esistente scritto per Boost.Asio. Voglio integrarli senza utilizzando un thread aggiuntivo.

C'è qualche riferimento su come farlo per Qt4 (preferito) o GTKmm?

Grazie.

Modifica

Voglio chiarire diverse cose per facilitare la risposta. Sia Qt che GTKmm forniscono " seleziona come " Funzionalità:

Quindi, la domanda è: come integrare " selettori / poller " come reattore a Boost.Asio io_service . Oggi Boost.Asio può utilizzare select, kqueue, epoll, / dev / poll e iocp come servizio di reattori / proattori. Voglio integrarlo nel ciclo principale del framework GUI.

Eventuali suggerimenti e soluzioni (meglio) sono i benvenuti.

È stato utile?

Soluzione

È una domanda piuttosto vecchia ma per coloro che la stanno leggendo ora vorrei condividere il mio codice che è un'implementazione di QAbstractEventDispatcher per boost :: asio.

Tutto ciò che serve è aggiungere la seguente riga prima di creare QApplication (di solito è in main ()).

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

Ciò causerà che io_service viene eseguito insieme all'applicazione qt in un thread senza ulteriore latenza e calo delle prestazioni (come in soluzione con la chiamata io_service :: poll () " di volta in volta ").

Sfortunatamente, la mia soluzione è solo per sistemi posix, poiché usa asio :: posix :: stream_descriptor. Il supporto di Windows potrebbe richiedere un approccio completamente diverso o abbastanza simile - non lo so davvero.

Altri suggerimenti

Semplice: Crea uno slot QT che chiami io_service :: poll_one () appartenente alla GUI. Collega quello slot al segnale tick di QT.

Approfondimento: Fortunatamente per te Boost.Asio è molto ben progettato. Esistono molte opzioni su come fornire un thread di esecuzione agli interni asincroni sottostanti. Le persone hanno già menzionato l'uso di io_service :: run () , una chiamata bloccante con molti svantaggi.

Puoi accedere ai widget gui solo da un singolo thread. I thread esterni in genere devono pubblicare eventi nella GUI se vogliono mutare qualsiasi widget. Questo è molto simile a come funziona Asio.

L'approccio ingenuo è quello di dedicare un solo thread (o timer) all'esecuzione di io_service :: run () e fare in modo che il gestore del completamento di Asio invii un segnale gui. Questo funzionerà .

Invece puoi usare la garanzia che i gestori di completamento saranno chiamati solo nel thread di esecuzione del chiamante io_service . Non fare in modo che il thread della gui chiami io_service :: run () poiché blocca e potrebbe bloccare la gui. Usa invece io_service :: poll () o io_service :: poll_one () . Questo farà sì che tutti i gestori di completamento Asio in sospeso vengano chiamati dal thread gui. Poiché i gestori sono in esecuzione nel thread della GUI, sono liberi di modificare i widget.

Ora devi assicurarti che io_service abbia la possibilità di funzionare regolarmente. Raccomando di ripetere alcune volte il segnale gui ripetitivo poll_one () . Credo che QT abbia un segnale di spunta che farebbe il trucco. Ovviamente puoi inviare il tuo segnale QT per un maggiore controllo.

Se capisco correttamente la tua domanda, hai un codice scritto per Boost.Asio. Desideri utilizzare quel codice all'interno di un'applicazione GUI.

Ciò che non è chiaro nella tua domanda è se vuoi avvolgere i livelli di rete Qt / Gtk attraverso asynio affinché il tuo codice funzioni, se stai solo cercando una soluzione per avere sia un loop di eventi gui che un asynio insieme.

Assumerò il secondo caso.

Sia Qt che Gtk hanno metodi per integrare eventi stranieri nel loro ciclo di eventi. Vedi ad esempio qtgtk dove il loop degli eventi Qt è collegato a Gtk.

Nel caso specifico di Qt, se si desidera generare eventi per Qt, è possibile utilizzare la seguente classe: QAbstractEventDispatcher .

Dopo una rapida occhiata a boost asio, penso che devi fare quanto segue:

  • hanno un QTimer ricorrente con durata zero che chiama io_service :: run () per tutto il tempo. In questo modo, boost :: asio chiamerà il tuo gestore di completamento non appena l'operazione asincrona sarà completata.
  • nel gestore del completamento, due opzioni:
    • se l'operazione di completamento è lunga, separata dalla GUI, fai la tua attività e assicurati di chiamare qApp.processEvents () regolarmente per mantenere la GUI reattiva
    • se vuoi solo comunicare di nuovo con la gui:
      1. definisce un tipo QEvent personalizzato
      2. iscriviti a questo evento
      3. pubblica il tuo evento nel loop degli eventi Qt usando QCoreApplication :: postEvent ( ) .

È possibile integrare autenticamente i loop principali è . È solo un grande dolore (e devo ancora provarlo).

L'esecuzione di io_service :: run () su un thread separato è probabilmente la strada da percorrere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top