2016-02-22 12 views
7

Nel suo Qt event loop, networking and I/O API talk, Thiago Macieira afferma che la nidificazione di QEventLoop 's dovrebbe essere evitato:Perché si dovrebbe evitare l'annidamento di QEventLoops?

QEventLoop è per l'evento di nidificazione Loops ... Evitate, se potete, perché crea una serie di problemi: le cose potrebbero rientrare , nuove attivazioni di socket o timer che non ti aspettavi.

Qualcuno può espandersi su ciò a cui si riferisce? Mantengo un sacco di codice che utilizza le finestre di dialogo modali che annidano internamente un nuovo ciclo di eventi quando viene chiamato exec(), quindi sono molto interessato a sapere che tipo di problemi questo può comportare.

risposta

8
  1. Un ciclo di eventi nidificati costa 1-2kb di stack.

  2. Ha la capacità di immettere nuovamente qualsiasi codice già presente nello stack di chiamate. Non ci sono garanzie che qualcuno di quel codice sia stato progettato per essere rientranti. Sto parlando del tuo codice, non del codice di Qt.

  3. Nel corrente Qt, ci sono due posti in cui, a causa di un bug di vecchia data API o inadeguatezze della piattaforma, è necessario utilizzare annidato exec: QDrag di file e piattaforma di dialoghi (su alcune piattaforme). Semplicemente non hai bisogno di usarlo da nessun'altra parte. non è necessario il ciclo di eventi nidificati per le finestre di dialogo modali non di piattaforma.

  4. Rientrando il ciclo degli eventi è di solito causata da scrivere codice pseudo-sincrono in cui ti lamenti la mancanza di yield(), nascondere la testa sotto la sabbia e di utilizzare invece exec(). Tale codice in genere finisce per essere spaghetti e non è necessario. La scrittura pulita del codice asincrono viene generalmente effettuata tramite macchine a stati, vedere this answer per un esempio e QP framework per un'implementazione diversa da QStateMachine.

+0

Grazie per la risposta. Hai qualche idea su "nuove attivazioni di socket o timer che non ti aspettavi"? – MuchToLearn

+0

@MuchToLearn Questo è ciò che significa reinserire il codice. Il codice in cui si chiama 'exec' può essere, in generale, chiamato di nuovo. L'origine di tali eventi potrebbe essere l'interfaccia utente, ma potrebbero essere timer, socket, eventi della piattaforma nativa, ecc. –

+0

La macchina di stato è come un paradigma mancante per completare la programmazione orientata agli oggetti, funzionale e dichiarativa. – doc

0

Un ciclo di eventi nidificati provoca l'inversione dell'ordine. (Almeno su Qt4)

Diciamo che avere la seguente sequenza di cose che accadono

enqueued in outer loop: 1,2,3 
processing 1 => spawn inner loop 
enqueue 4 in inner loop 
processing 4 
exit inner loop 
processing 2 

in modo da vedere l'ordine di elaborazione era: 1,4,2,3.

Parlo per esperienza e questo di solito ha provocato un crash nel mio codice.

+0

Interessante. Presumo che ci fosse un vincolo di ordine nel tuo codice che lo ha fatto crash? Puoi andare più nel dettaglio su che tipo di eventi erano? Non vedo a priori come l'evento 4 di accodamento nel ciclo interno faccia in modo che venga elaborato per primo o crash del codice. – MuchToLearn

+0

Ovviamente il codice si basa su una sequenza di messaggi. Un puntatore verrebbe inizializzato sul primo evento e l'oggetto invocato sul secondo evento e si arresterebbe in modo anomalo con seg-fault. È una cosa valida affidarsi all'ordine se le cose non sono idempotenti. – mhstnsc

+0

@MuchToLearn Questa cosa è stata di recente un problema nella mia squadra in quanto qualcuno voleva fare una richiesta HTTP e voleva attendere il risultato con il loop interno. Alla fine si è deciso a bloccare il eventloop, cioè se non è una cosa dell'interfaccia utente altrimenti le cose possono diventare disastrose perché introdurre un passo asincrono sarebbe piuttosto virale per le API ma se hai preso il qt, quindi sii pronto a pagare il prezzo :) – mhstnsc