Solved L'esecuzione di una routine richiamata da un signal avviene con leggero ritardo
-
Buongiorno.
Ho un modulo thread che fa un loop continuo e si ripete ogni 3 secondi. Dall'interno di questo modulo, emetto un segnale per attivare una routine che aggiorna il form del modulo windowmain. Ho appurato che mentre il modulo thread effettua il quarto loop e lancia il signal per attivare la routine che aggiorna il form, la routine non parte subito, ma si avvia solo quando il loop sarà passato alla quinta iterazione. Dovrei forzare l'esecuzione rigorosamente pedissequa, ma come posso fare una cosa del genere ?- emetto il signal
- perde tempo finché la routine non si sarà conclusa
- prosegue
-
Ciao...
e com li chiami qui 3 secondi.. in una slot come tipo:QTimer::singleShot(i * 1000, this, SLOT(PrintScreen()));
Di regola funzionano bene in codice ordinato e richiamare funzioni ogni 500 millisecondi a me non danno mai problemi .. come del tipo di attesa di conversione dei file...
-
Ho questa situazioni.
- Il main attiva un thread e lo rende a loop infinito così:
HRnet_0490 = new HRnet_0490_Qthread; HRnet_0500 = new HRnet_0500_Elaborazione; HRnet_0500->moveToThread(HRnet_0490); HRnet_0490->start(); QObject::connect(HRnet_0490, SIGNAL (started()), HRnet_0500, SLOT (emitThread()));
Il modulo HRnet_0500 gira per tutta l'esecuzione del programma ed è in attesa che si schiacci un pulsante che avvii l'esecuzione di alcune istruzioni finché non si ripigia il tasto per metterlo in attesa. Come ultime istruzioni di questo gruppo while (true) ho un msleep(3000) per farlo "looppare" dopo 3 secondi.
Ad ogni fase del loop, il programma va ad incrementare l'indice di una matrice di molti elementi e, solo in determinati casi, scatenare la scrittura di dati a video.
Ebbene, nel momento in cui vado ad elaborare l'incremento dell'indice e popolare di dati la matrice, ho l'istruzione "int ultind = HRnet_0110->LeggiProgrEstrattoFISSO();" che mi dà nella variabile ultind il valore 5. Elabora, fa calcoli e decide di visualizzare il risultato, quindi lancia un "emit SignalMostra". All'interno del modulo mainwind c'è lo slot SignalMostra e la prima istruzione di questo slot è l'identica istruzione vista prima: ovvero "int ultindprodotto = HRnet_0110->LeggiProgrEstrattoFISSO();" ma, stranamente, consultando il valore di questo ultindprodotto lo trovo impostato a 4: come se stesse eseguendo la routine ancor prima che sia finita la popolazione del quinto indice.
Però, mi sa che sto inventando la macchina del tempo: richiamo una routine alla quinta iterazione e questa dice che mi trovo ancora alla quarta. :-)
Scherzi a parte, evidentemente l'avvio dello slot per la visualizzazione dei dati non riesce a tenere conto che l'elaborazione si trova già all'elemento successivo. Non so che fare. -
Guarda.... la strada bella è sempre organizzata pulita controllata nei minimi dettagli con molta passione.
Tu invece per venire a capo devi traciare tutti i percorsi nel minimo dettaglio e seguire bene i SLOT che questi sono precisi...
Vale a dire debug & debug fino che tutto fila dritto...
E tutto cosa posso dirti non vedendo molto codice...
ma mi sembra strano che aspetti un emit da HRnet_0490 semmai è il Worker Thread ch dice he ha finito...
saluti....#if 0 //// 1 or 0 #define EPUBDEBUG qDebug #define STAGE 1 #else #define EPUBDEBUG \ if (0) \ qDebug #define STAGE 0 #endif
-
Grazie. Proverò ma mi vedo su una strada molto tortuosa.
-
Credo che qui il problema e' che vorresti che Qt gestisse la sincronizzazione dei thread, cosa che non puo' fare.
Per farti capire cosa sta succedendo devi avere l'intuizione di come funziona l'event loop in Qt.
QApplication::exec()
,QEventLoop::exec()
, eQThread::exec()
fannu tutti partire un event loop che puoi immaginare sia una cosa tipo:while(true) QApplication::processEvents();
Quando connetti un segnale dal thread2 al thread principale (gui thread) e questo viene emesso, viene automaticamente messo in coda (Qt::QueuedConnection) nel gui therad e viene eseguito non appena quel thread raggiunge l'istruzione
QApplication::processEvents();
. Questo perche' il thread2 non ha idea di cosa stia facendo il gui thread, quindi gli dice "quando hai tempo, processa quello slot", questo evita race conditions. Non c'e' modo di evitare (in generale) race conditions se vuoi che lo slot venga eseguito istantaneamente. Puoi forzare la connessione tra signal e slot ad essere istantanea aggiungendo Qt::DirectConnection come ultimo argomento aconnect()
ma questo significa che sta a te assicurarti di non avere race conditions usando mutex (std::mutex
,QMutex
,QReadWriteBlock
, etc.) o atomic (std::atomic<T>
) -
Grazie. Ho capito che devo studiare di più.