Ott hagytuk abba, hogy egy bizonytalan ideig futó ciklust nem illik betenni egy modal ablakba. Akkor válasszuk le a ciklust a modal ablakról. Itt szintén több megoldás van:
- elindítunk egy külön programot (processzt) ami elvégzi a dolgát, esetünkben korábban elindított programok leállítását. Ennek hátulütője, hogy ezt a programot is le kell valahogy állítani.
- elindítunk egy programot a programon belül, vagyis egy thread-et. Ez is önálló életre kel, de könnyebb kezelni és különben is, ilyet még nem írtunk.
A Thread kezelés alapjait fogjuk most áttekinteni. Legyen a szál a gyerek, a hívó osztály a szülő. A thread (szál) :
- prioritása állítható
- önálló eseménykezelője (eventloop) van
- kommunikálhat más szálakkal
- szinkronizálható a szálak működése
- futása felfüggeszthető
- op. rendszer független
A szál egy sima osztály némi megkötéssel:
- a QThread osztályból ered (class myThread : public QThread)
- ha connect utasítást használunk Q_OBJECT kell
- futását a "run" utasítás vezérli
- a deklarált változók tulajdonosa változik
A szál alap felépítése:
myThread.h
class myThread : public QThread {
Q_OBJECT
public:
myThread();
~myThread();
void run();
private:
QObject *v_1,*v_2,*v_3,*v_4;
void futtato();
private slots:
void mySlot();
}
myThread.cpp
myThread::myThread{
v_3 = new QObject();
}
~myThread::myThread{
delete v_1;
delete v_2;
delete v_3;
delete v_4;
}
void myThread::futtato(){
v_4 = new QObject();
}
void myThread::run(){
v_1 = new QObject();
exec();
return;
}
void myThread::mySlot(){
v_2 = new QObject();
}
Indítása a szülőből történik.
myThread = new myThread();
myThread->start();
A start() hívja meg a szál run() függvényét. Mire való a run() függvény? Itt lehet előkészítő munkákat végezni, és ez kezeli a szál eseménykezelőjét. A szálból kilépni return-el lehet, az eseménykezelőből az exit(int érték) és a quit() utasításokkal tudunk. A quit() mindig nullát ad vissza az exec() visszatérő értékének, az exit() az általunk megadottat. Az exec() tuképp egy végtelen ciklus. Természetesen illik a szál befejezésekor a lefoglalt memóriát (malloc, new) felszabadítani.
A deklarált változók tulajdonos változására a példa:
A v_1 a szülő osztályhoz fog tartozni, mert a run() függvényben kapott értéket, a többi változó a szálhoz (myThread) kötődik. Ezért a destruktorban hibaüzenetet kapunk, miszerint a v_1 változót nem tudjuk törölni, tekintve, hogy másik osztály a szülője. Ugyanez igaz akkor is, ha a futtató() függvényt a run()-on belül indítjuk. Ekkor minden, a futtatóban értéket kapó változó a szülő tulajdonába kerül. De ha a futtato()-t a konstruktorból indítjuk, akkor a gyerek (szál) lesz a változók tulajdonosa, és így a myThread osztály többi függvényében is tudjuk kezelni őket. Ezt a csomót empírikus úton feloldva az "értékes" függvényeket a konstruktoron keresztül indítom, a run()-ban csak az eseménykezelőt hagyom.
Egy változóhoz tartozó szál nevét a currentThread()
(qDebug() << v_2->currentThread()) függvénnyel tudom kiiratni. Változók tulajdonosát a moveToThread(QThread * targetThread)-el változtathatom, de csak egy irányban.
This function can only "push" an object from the current thread to another thread, it cannot "pull" an object from any arbitrary thread to the current thread
Jó szórakozást:)