Qthread: esempio funzionante
-
Tuttle le variabili globali sono race conditions in questo esempio e hai pure un potenziale memory leak del thread (se chiudi la finestra prima che il thread finisca tutto crasha).
Non puoi usare direttamente cose che non vivono sullo stesso thread. O proteggi l'accesso in qualche modo (
std::atomic
QMutex
,QReadWriteLock
, etc.) o, come sarebbe meglio, deleghi al thread che posside gli oggetti l'onere di leggerli/scriverli (usando signals e slots per comunicare tra i threads.P.S.
- le variabili globali sono nel 99% dei casi errori di design.
goto
urta la vista di qualsiasi programmatore in quanto e' un incubo da debuggare. evitalo come la peste. nel tuo caso puoi usaredo{}while();
-
Ho speso troppo tempo a debuggare codice con goto da odiarlo con tutto me stesso.
Se mi capita di vedere un goto nella code review per me e' uno stop istantaneo quindi capisco di esser "di-parte" ma la maggior parte delle volte se goto semplifica il codice significa che inserendo una funzione separata si semplifica ancora di piu'
-
Allora eviterò di usare i goto almeno nelle routines che posto, per evitare di perdere la tua preziosa consulenza.
Per mia cultura... come dovrei modificare il Modulo_Loop_Eterno per fare in modo che scriva sul form gestito da MainWindow ? In fondo dentro Modulo_Loop_Eterno c'è semplicemente l'istruzione ptr_mainwindow->aggiungi_contatore(); : quindi l'append nel form è fatto dallo stesso modulo che lo ha creato. Non va bene così ? -
@bvox123 said in Qthread: esempio funzionante:
per evitare di perdere la tua preziosa consulenza
In realta' era un pianto lamentativo generico. se i tuoi manager/clienti accettano goto chi sono io per fermarti?!
Non va bene così ?
No, per capirlo prova a immaginare cosa succede se nel thread principale chiami
delete ptr_mainwindow;
(che per la cronaca succede quando chiudi la finestra se non cambi le flag di QApplication).come dovrei modificare il Modulo_Loop_Eterno per fare in modo che scriva sul form gestito da MainWindow ?
definisci un
Q_SIGNAL void aggiungi_contatore();
poi connetti quel segnale a un nuovo slot nella main window che si prende cura di aggiornare il contatore -
Mettiamola così.
Forse non sai che una volta, prima dell'avvento delle scuole medie i ragazzi, dopo la quinta elementare, frequentavano la sesta, la settima e l'ottava: non davano un titolo di studio, ma permetteva agli studenti di continuare negli studi. Bene, io sono uno di quelli, non ho un capo manager, ma sono manager di me stesso e sono anche molto esigente: me ne dico spesso di tutti i colori.
Ora sono tornato in prima elementare, dato che le conoscenze acquisite 40 anni fa sono obsolete a vantaggio di cose strane: le classi, con signals e slot. E allora...
nel Modulo_Loop_Eterno.h aggiungo Q_SIGNAL void aggiungi_contatore(); fra i Signals.
poi nel modulo Modulo_Loop_Eterno.cpp sostituisco ptr_mainwindow->aggiungi_contatore(); con QObject::connect(this, SIGNAL (aggiungi_contatore()), ptr_mainwindow, SLOT (aggiungi_contatore()));
Ho fatto così, ma la routine mainwindow::aggiungi_contatotore() non riesce ad indirizzarla, emettendo i seguenti errori al momento esecuzione:
Contatore: 4
QObject::connect: No such slot MainWindow::aggiungi_contatore() in ../ProvaThread/modulo_loop_eterno.cpp:34
QObject::connect: (receiver name: 'MainWindow')
Contatore: 5
QObject::connect: No such slot MainWindow::aggiungi_contatore() in ../ProvaThread/modulo_loop_eterno.cpp:34
QObject::connect: (receiver name: 'MainWindow')
Cosa dovrei aggiungere ? (Per favore, ricordati che sono in prima elementare). -
no, al posto di
ptr_mainwindow->aggiungi_contatore();
ci vaemit aggiungi_contatore();
.il connect va dove metti tutti gli altri connect, dopo
istanza_Modulo_Loop->moveToThread(istanza_QThread);
L'idea e' che il thread secondario "parla" attraverso i
signals
, il thread primario li ascolta e agisce di conseguenza. il thread secondario non agisce mai, dice solo al primario cosa fare -
Va bene, ma come fa a capire che la routine aggiungi_contatore si trova nel mainwindow ? E' solo nel mainwindow che ho inserito quei connect, quindi se questo nuovo lo devo aggiugere a quelli già presenti, non ci sarà nessun posto, all'interno di Modulo_Loop_Eterno, in cui si indirizza a mainwindow. Sbaglio ?
-
Ho messo QObject::connect(istanza_Modulo_Loop, SIGNAL (aggiungi_contatore()), this, SLOT (aggiungi_contatore())); fra gli altri connect ma in esecuzione mi dice che non riconosce la routine aggiungi_contatore così:
QObject::connect: No such slot MainWindow::aggiungi_contatore() in ../ProvaThread/mainwindow.cpp:35
QObject::connect: (receiver name: 'MainWindow') -
@bvox123 said in Qthread: esempio funzionante:
Sbaglio ?
No, e questo e' esattamante l'obbiettivo. uno dei principi S.O.L.I.D. si focalizza sul fatto che ogni classe deve fare 1 cosa e una cosa sola. nel tuo caso
Modulo_Loop_Eterno
deve solo occuparsi del contatore, non e' il suo lavoro sapere cosa aggiornare nella GUI. infatti,Modulo_Loop_Eterno
non dovrebbe nemmeno sapere se una gui esiste o no -
Scusa me l'ero perso.
aggiungi_contatore
e' inpublic:
non inpublic slots:
o lo dichiari come slot o (probabilemte preferibile) usi la connect di Qt5QObject::conect(istanza_Modulo_Loop,&Modulo_Loop_Eterno::aggiungi_contatore,this,&MainWindow::aggiungi_contatore);