Seite 1 von 2
[gelöst] QThread startet QThreads blockweise
Verfasst: 1. Februar 2008 19:38
von wobaa666
Hallo,
ich bin erst vor Kurzem von einem anderen Framework (wxWidgets) auf Qt umgestiegen. Unter Qt komme ich irgendwie mit komplexeren Thread Sachen nicht mehr klar.
Ich versuche folgendes zu realisieren (unter wx hab ich eine Lösung, die sich leider nicht 1:1 umsetzen lässt).
Folgendes: ich habe einen Workerthread (QThread) und der soll 100 CalcThreads (QThread) starten, jedoch so, das immer nur 5 gleichzeitig aktiv sind. Und immer wenn einer fertig wird, wird ein neuer gestartet, bis alle 100 abgearbeitet sind.
Kann mir mal jemand mit Pseudocode oder gleich Qt Code schreiben, wie ich da am Besten vor gehe und worauf ich achten muss?
Wollte das so machen, das ich in einem Array / Vector immer die 5 aktiven Threads verwalte und die sich dann beim Signal "finished()" automatisch aus dem Array austragen, so das der Platz neu befüllt werden kann.
Irgendwie klappt das vorn und hinten nicht. Vielleicht hab ich auch nur ne Denkblockade.
Deswegen ist jeder Hinweis willkommen.
Danke!
Verfasst: 1. Februar 2008 20:14
von PeterLustig
Also ich würde eine Slot-Funktion in deinem Workerthread erstellen. Das finished Signal verbindest du dann mit diesem Slot. In diesem Slot startest du dann den nächsten Thread. Am Anfang dann eben 5 Threads starten.
Verfasst: 1. Februar 2008 20:15
von Christian81
Die Idee ist soweit ok. Was ich nicht verstehe ist warum man dann überhaupt 100 threads braucht. Die neuen Threads würde ich erst erzeugen (oder eben die alten wiederverwenden) wenn ein alter fertig ist.
Was klappt denn nicht?
Verfasst: 1. Februar 2008 20:23
von wobaa666
Hier mal meine erste Herangehensweise:
Code: Alles auswählen
int numThreads = 0;
int numCalc = 100;
void Worker:run() {
while(numThreads < 5 && numCalc > 0) {
CalcThread* calc = new CalcThread();
connect(calc, SIGNAL(finished()), this, SLOT(OnCalcFinished());
calc->start();
numThreads++;
numCalc--;
}
while(numThreads > 0) {
qDebug() << "es laufen noch threads";
}
}
void Worker::OnCalcFinished() {
numThreads--;
}
Dadurch, das ich in der Worker::run() ein while mache, komm ich anscheinend nie in den Genuss auch mal ein finished() signal zu erhalten. Damit startet er mir 5 Threads und dann ists ne Endlosschleife.
In der Doku steht, das ich im Worker ein exec() einbauen müsste, damit ich in den EventLoop starte. Ich habe aber keine Ahnung an welcher Stelle das sein sollte.
wäre ein Timer vielleicht die Lösung für das ungeschickte while?
Verfasst: 1. Februar 2008 20:40
von upsala
Kannst du Qt4.4 abwarten? Dann verwende QFuture...
Verfasst: 1. Februar 2008 20:54
von Christian81
Sobald du ::run() verlässt sind deine Threads weg.
Schau Dir mal die thread-Beispiele an.
Verfasst: 1. Februar 2008 21:22
von wobaa666
Christian81 hat geschrieben:Sobald du ::run() verlässt sind deine Threads weg.
ja, das ist mir klar. durch meine Endlosschleife verlässt er ja nie das run. Ist ja aber auch kein Problem nen Thread als Membervariable zu deklarieren. Aus :run() möchte ich ja auch erst raus, wenn 100x der CalcThread aufgerufen wurde und diese fertig sind.
Ich bekomme leider kein finished() Signal an den Worker zurück. Hab das Ganze jetzt mal nur mit einem Thread versucht, aber da bekomm ich auch kein Signal gesendet.
Code: Alles auswählen
CalcThread calc;
void Worker:run() {
connect(&calc, SIGNAL(finished()), this, SLOT(OnCalcFinished());
calc->start();
exec();
}
void Worker::OnCalcFinished() {
qDebug() << "Thread finished()";
}
Woran liegt es, dass das SIgnal nicht ankommt, oder nicht darauf reagiert wird?
Verfasst: 1. Februar 2008 21:27
von Christian81
Stimmt - habe mich verschaut.
Da Du nicht in der Eventloop bist, kann der Thread auch kein Signal bekommen.
Verfasst: 1. Februar 2008 21:36
von wobaa666
Christian81 hat geschrieben:Da Du nicht in der Eventloop bist, kann der Thread auch kein Signal bekommen.
In der Doku steht zu QThread::exec(): "It is necessary to call this function to start event handling. "
Schön und gut, aber wo und wann? im letzten Code, den ich gepostet habe, ist das exec() drin, dennoch kommt kein Signal.
Wenn Du mir verraten könntest, wie ich den Worker Thread zu einem EventLoop überreden kann, würde mir das sicher viele graue Haare sparen.
Wenn die Signale ankommen, sollte es auch kein Problem sein, die mehrere Threads zu clustern.
Verfasst: 1. Februar 2008 21:38
von Christian81
das exec() ist korrekt. Aber ggf. dein connect() nicht.
Außerdem weiss ich nicht ob sich deine anderen Threads überhaupt beenden.
Verfasst: 1. Februar 2008 21:50
von wobaa666
Also mein CalcThread sieht in etwa so aus:
Code: Alles auswählen
class CalcThread : public QThread
{
public:
void run();
};
void CalcThread::run()
{
qDebug() << "CalcThread::run()";
}
Das "CalcThread::run()" wird auch ausgegeben
Hab in dem Thread auch schon mit exec() rum gespielt, immer ohne Erfolg.
Qt meldet auch keinen Hinweis, dass das connect gescheitert ist.
Viele Grüße, Jan
Verfasst: 1. Februar 2008 21:55
von Christian81
Also eigentlich kann nur das connect nicht funktionieren. Was anderes fällt mir nicht ein

Verfasst: 1. Februar 2008 21:58
von wobaa666
Ich glaub das wird ne lange Nacht
Ist ja schon mal etwas, wenn es zumindest theoretisch funktionieren müsste.
Danke erst einmal!
Verfasst: 1. Februar 2008 22:00
von Christian81
Ach ich rede Müll - das Signal kommt natürlich, ist aber beim exec() schon längst weg - zu schnell beendet. Zumindest denke ich es.
Verfasst: 1. Februar 2008 22:10
von wobaa666
Ich habe ein sleep(10) in den CalcThread:run() eingebaut. Danach dann die Ausgabe.
Hab mit'm Debugger geprüft, ob er auch vorher in das Exec() von Worker rein geht. Das passt. Nach ner ganzen Weile kommt dann halt die Ausgabe auf der Konsole, aber trotzdem kommt kein Signal.
Kann das irgend etwas mit dem Q_OBJECT in der Klassendefinition zu tun haben?
Ich habe es momentan bei beiden Threads drin. Sowohl Worker als auch Calc.