2009-09-06 13 views
23

Main (la funzione main è presente) thread del mio programma è riservato per attività non GUI. Chiama un numero di lunghe funzioni di calcolo. Tutte le GUI implementate hanno svolto il loro lavoro in thread separati.Come far funzionare Qt quando il thread principale è occupato?

Ora implementerò un'altra GUI utilizzando Qt. Qt documentation dice che tutte le attività relative alla GUI dovrebbero essere fatte nel thread principale. Nel mio caso, l'inserimento di chiamate occasionali di QCoreApplication :: processEvents() nel thread principale sarebbe praticamente inutile a causa di notevoli ritardi tra di loro.

C'è un modo per superare questo limite di Qt? E 'impossibile fare qualcosa di non-GUI nel thread principale del programma Qt?

+4

Perché non si può fare il vostro lavoro su un altro thread? – Kornel

+1

Solo per ragioni storiche. Il refactoring sarà un dolore, quindi ho pensato di fare qualche ricerca se è evitabile. – Basilevs

risposta

20

No, dovresti eseguire i calcoli in una discussione separata. Come hai già detto, c'è un work-around disponibile in QCoreApplication::processEvents(), ma sembra che tu non sia in grado di farlo funzionare per te.

Se non si desidera eseguire tutto il lavoro di impostazione di QThread e spostare tutto il codice, è possibile che la funzione QtConcurrent::run sia utile: consente di eseguire una funzione in modo asincrono.

Alcune indicazioni: si dovrebbe cercare di mantenere il filo principale (GUI) il più leggero possibile. Grandi quantità di IO o calcoli dovrebbero essere eseguiti in modo asincrono usando QtConcurrent :: run, o eseguiti all'interno di un QThread separato. A seconda della complessità del tuo codice, potresti riuscire a farla franca con il metodo QtConcurrent.

+1

Non vedo il grande vantaggio dell'utilizzo di QtConcurrent :: run() anziché di QThread. In realtà è più lavoro in questo modo. Segui QThread, è molto più semplice implementare –

+2

Dipende da cosa stai facendo e da come è strutturato il tuo programma. Se è necessario un thread permanente che deve essere sempre in esecuzione, utilizzare QThread. Se sono necessari molti piccoli compiti (spesso indipendenti) da eseguire e non ti interessa quali sono in esecuzione a che ora, quindi utilizzare QtConcurrent. – Thomi

+0

Sì, sono d'accordo che avrei potuto essere un po 'duro ... come dici tu dipenda da cosa ti serve. –

4

È meglio scaricare i lunghi calcoli su altri thread in modo che il thread della GUI principale rimanga reattivo. Il modo uniprocessing vecchio stile di fare le cose sarebbe essere quello di assicurarsi che i calcoli non vengano mai eseguiti per troppo tempo senza il polling del gestore di eventi GUI, ma che non si adatti ai multi-core.

Fortunatamente Qt ha un eccellente threading support. In passato si avrebbe dovuto roll-si-proprio sistema, ad esempio per l'agricoltura dei compiti ad un pool di thread utilizzando QThread, QMutex, QWaitCondition ecc, ma recenti versioni di Qt hanno reso le cose più facili con astrazioni di livello superiore come QThreadPool, QtConcurrent::run e QFuture .

+1

Perché non utilizzare le connessioni di QObject tra i thread? –

0

Non so come andranno le cose se chiami QApplication :: exec() da un altro thread, che diventa il tuo thread GUI. Solo un'idea

(Fateci sapere se funziona, sarebbe interessante ...)

+0

Perché vorresti farlo?Se hai bisogno di fare il lavoro per sputare il tuo codice ed eseguirne metà su un thread diverso, puoi farlo anche correttamente ... o mi manca qualcosa? – Thomi

+0

Non sto raccomandando, sto solo dando un consiglio su come ottenere esattamente ciò che l'OP ha chiesto. La ragione potrebbe essere altre librerie che richiedono roba fatta nel thread principale. (IIRC, OpenSG 1.x richiede il rendering e il caricamento da eseguire nello stesso thread, quindi ci siamo ritrovati con un pesante disegno OpenGL nel thread principale (dal momento che abbiamo caricato tutti i grafici in quel thread) .Non è divertente avere anche una GUI in esecuzione (ma è stato risolto in 2.x, IIRC) – Macke

+1

Puoi farlo, l'abbiamo appena fatto con una semplice applicazione e ha funzionato, ma quando il nostro programma si arresta, si ottiene un errore gratuito non valido() o un errore double free() – dgrant

Problemi correlati