[gelöst] QThread startet QThreads blockweise

Alles rund um die Programmierung mit Qt
wobaa666
Beiträge: 9
Registriert: 1. Februar 2008 19:20

[gelöst] QThread startet QThreads blockweise

Beitrag 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!
Zuletzt geändert von wobaa666 am 2. Februar 2008 20:40, insgesamt 1-mal geändert.
PeterLustig
Beiträge: 386
Registriert: 21. November 2007 20:07

Beitrag 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.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
wobaa666
Beiträge: 9
Registriert: 1. Februar 2008 19:20

Beitrag 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?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Kannst du Qt4.4 abwarten? Dann verwende QFuture...
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Sobald du ::run() verlässt sind deine Threads weg.
Schau Dir mal die thread-Beispiele an.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
wobaa666
Beiträge: 9
Registriert: 1. Februar 2008 19:20

Beitrag 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?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Stimmt - habe mich verschaut.

Da Du nicht in der Eventloop bist, kann der Thread auch kein Signal bekommen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
wobaa666
Beiträge: 9
Registriert: 1. Februar 2008 19:20

Beitrag 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.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

das exec() ist korrekt. Aber ggf. dein connect() nicht.
Außerdem weiss ich nicht ob sich deine anderen Threads überhaupt beenden.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
wobaa666
Beiträge: 9
Registriert: 1. Februar 2008 19:20

Beitrag 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
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Also eigentlich kann nur das connect nicht funktionieren. Was anderes fällt mir nicht ein :)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
wobaa666
Beiträge: 9
Registriert: 1. Februar 2008 19:20

Beitrag von wobaa666 »

Ich glaub das wird ne lange Nacht ;)
Ist ja schon mal etwas, wenn es zumindest theoretisch funktionieren müsste.

Danke erst einmal!
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
wobaa666
Beiträge: 9
Registriert: 1. Februar 2008 19:20

Beitrag 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.
Antworten