[gelöst] QThread und Signal finished()

Alles rund um die Programmierung mit Qt
TheBert
Beiträge: 21
Registriert: 1. September 2009 14:27

[gelöst] QThread und Signal finished()

Beitrag von TheBert »

Hallo,

ich befasse mich gerade mit threads und habe ein problem mit dem signal finished().

Ich habe folgendes erstellt:

Code: Alles auswählen

void MyClass::buttonStartThread_clicked()
{
    _thread = new QThread();
    dataManager = new DataManager();

    connect(_thread, SIGNAL(started()), dataManager,SLOT(handleData()));
    connect(_thread, SIGNAL(finished()), this, SLOT(threadFinished()));

    dataManager->moveToThread(_thread);
    _thread->start();
}

void MyClass::threadFinished()
{
   qDebug()<<"thread finished!";
}
Ist mein vorgehen bei threads so richtig? Läuft meine klasse dataManager in der eventloop des threads oder läuft noch in der main eventloop?

Und warum wird das signal finished() nie aufgerufen?

Danke!
Zuletzt geändert von TheBert am 18. November 2010 19:05, insgesamt 1-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Vielleicht weil dein Thread nicht beendet wird - sieht man hier ja nicht.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Mani99
Beiträge: 244
Registriert: 15. April 2009 10:46
Wohnort: München

Beitrag von Mani99 »

Ich bin mir nicht sicher ob ich das mit den threads überhaupt richtig mache?

Ich glaube (sogar von dir) gelesen zu haben, das es nicht immer notwendig ist, von QThread abzuleiten und run neu zu implementieren, sondern so wie in dem beispiel mit moveToThread() das zu machen, oder habe ich da was falsch verstanden?
Zuletzt geändert von Mani99 am 18. November 2010 09:38, insgesamt 1-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Zur Zeit erzeugst Du einen Thread und startest ihn - nichts weiter.

Zum Beispiel:
Ich würde von QThread ableiten, in run() den dataManager erzeugen und per exec() die Eventloop starten. Wenn der dataManager fertig ist schickt er ein Signal an den Thread und er beendet sich.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Mani99
Beiträge: 244
Registriert: 15. April 2009 10:46
Wohnort: München

Beitrag von Mani99 »

@Christian: Danke!

@Herbert: Also von QThread ableiten und run() neu implementieren!
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Ich würde von QThread ableiten, in run() den dataManager erzeugen und per exec() die Eventloop starten.
So wie ich es seh, emitted er nur Signale aus dem thread raus, und empfaengt keine.
Ob er ne eigene Eventloop (Overhead!) dafuer braucht, wuerd ich von der Art des Jobs abhaengig machen, die er drinne auszufueheren gedenkt.
Darueber haben wir leider keine Infos ...
Also von QThread ableiten und run() neu implementieren!
Ja eigentlich das "Standardvorgehen" wenn man QThread verwendet.
Irgendwann war QTHread::run() mal abstract. Fand ich persoenlich besser als die Standardimpl die nu ne eigene loop startet.
Ich glaube (sogar von dir) gelesen zu haben, das es nicht immer notwendig ist, von QThread abzuleiten und run neu zu implementieren, sondern so wie in dem beispiel mit moveToThread() das zu machen, oder habe ich da was falsch verstanden?
MoveToThread brauchst per Definition nur wenn der QThread ne eigene eventloop hat. run nicht zu überschreiben macht genau dann Sinn, wenn Du im run nur die Eventloop selber starten willst (das ist eh scho die StandardImplementierung). Alle anderen Vorgaenge muessten dann von Events von aussen irgendwie getriggert werden.
Nen thread mit eigener Eventloop macht Imho nur Sinn, wenn du ne bidirektionale Kommunikation zwischen main und deinem Thread hasst.

Bei "klassischen" Threadmodellen hat man das eher nicht. Ob man nen eher eventbasierendes Threadmodell braucht, haengt von der Aufgabenstellung ab ... kann Implementationstechnisch nen Segen sein, oder aber auch nur sinnloder Overhead.
Also Ohne Infos ueber das was im Thread machen willst, koennen wir schlecht richtige Tipps geben.


Ciao ....
Mani99
Beiträge: 244
Registriert: 15. April 2009 10:46
Wohnort: München

Beitrag von Mani99 »

Also Herbert (TheBert) und ich bauen gerade an einem client/server dings.

Die frage war jetzt bezogen auf den server, welcher per socket daten empfängt, und die auswertung inkl. eventuellen datenbankabfragen in dem thread (DataManager) erledigen soll.

Vermutlich wird es jetzt besser sein, in diesem fall von QThread abzuleiten und die verarbeitung der daten dann im run() zu machen?
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Warum raten hier alle immer wieder zum Überschreiben der run-Methode?

@TheBert: dein Vorgehen ist gut so.. es gibt daran nichts auszusetzen... Der Vorteil gegenüber der Ableitung ist die erhöhte Flexibilität (du kannst DataManager so in einem beliebigen Thread laufen lassen (auch im Haupt-Thread). Ausserdem ist es schöneres OOP ("DataManager gehört zu einem Thread" nicht "DataManager ist ein Thread")

Dass finished() nicht kommt ist doch einfach: der Thread wird nach "handleData()" ja nicht beendet.. den kannst du beliebig oft wiederverwenden.. oder du verbindest ein Signal von "DataManager" mit "quit()" des Threads..

hth..
Mani99
Beiträge: 244
Registriert: 15. April 2009 10:46
Wohnort: München

Beitrag von Mani99 »

solarix hat geschrieben:Dass finished() nicht kommt ist doch einfach: der Thread wird nach "handleData()" ja nicht beendet.. den kannst du beliebig oft wiederverwenden.. oder du verbindest ein Signal von "DataManager" mit "quit()" des Threads..
Jetzt wo du es sagst, fällt es mir auch auf!

Der thread weiß ja nicht was in handle data passiert und ob handle data schon fertig ist!

Ich muss allso wenn handleData() fertig ist, ein singal emittieren, auf, wie du gesagt hast, quit();

Danke an alle für die denkanstöße, es war auch interessant, andere vorgehensweisen und denkansätze zu hören!
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Ausserdem ist es schöneres OOP
Naja .... wenn er schoen schreiben will, sollt er aber eher java nehmen als c++ :twisted:
Im Ernst, in C++ sollte Performance schon nen Thema sein, sonnst koennt man sich viel Aerger mit der Wahl der richtigen Programmiersprache schon ersparen :-)
Und ne Eventloop ist Overhaed !

Also Herbert (TheBert) und ich bauen gerade an einem client/server dings.
Prinzipiell: Um gescheit Threads zu programmieren, solltest Du definitiv wissen warum Du es brauchst, bzw. was genau Du parallelisieren willst.

Threads auf Teufel komm raus zu verwenden, macht eigentlich kein Sinn ...

Auf Alle Faelle wurd ich Dir empfehlen sowas wie nen Verhaltensdiagram (Activity Chart, UML) mal zu bauen fuer eure Anwendung.
Dort wuerd ich dann mal die "Blockierzeiten" eintragen, grob abgeschatzt natuerlich. EIgentlich sieht man dann recht schnell, wo man Threads braucht, bzw wo die Sinn machen.

Also Threading wegen auswertung bzw Datenaufarbeitung kann schon sinnvoll sein.

Threading wegen Datenbankabfragen ist nicht ohne. Die Frage ist da eher, welche Beschraenkung hat die DB in sachen threading. Gibt datenbanken(Anbindungen), die koennen nur 1 Thread ...
- könnte Sinn machen.
unbedingt lesenswert: Threads and the SQL Module

Threading wegen Sockets ist zweischneidig. "Frueher" hat man das gern eingesetzt ... der grund war, die recht "umstaendliche" Bedienung von Raw Sockets im Assynchronen Modus. Sockets sind aber von Natur aus Assynchron .... Und die QT tut alles moegliche, um dir die QSockets in Ihrer assynchronen Form schmackhaft zu machen. Warum sollt man das nicht annehmen (Wenn man schon QT benutzt) ?
- das dafuer Threads brauchst mit QT wag ich mal zu bezweifeln.

Das Socket, DB Abfrage, DatenAufbereitung in einen Thread gehoeren, kommt drauf an .... koennt man machen, muss man nicht. Aber in verbindung mit der QT wuerd ich den Socket zumindest schon mal rausnehmen.

Generell. Der Server, hat der ne GUI ? wenn nein, seids euch sicher dass ihr QT da verwenden wollt ? Als Alternative wuerd ich boost (sockets, asio ... ) vorschlagen. Zumnindest wuerd ich aber die QT statisch linken (beim server)

Ne weitere Frage, wie "Ernst" ist das Thema. Auf was kommt es euch bei dem Projekt an ...
- ist performance nen problem ?
- Kommt es aufs "Lernen" und üben in ner Projektumgebung an
- wieviel Zeit wollts in das Projekt stecken ?
- Ist das Ergebniss das Ziel, wollts schnell eine Lauffaehige version haben weil ihr das "Programm" braucht ?
...

Ciao ...
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

RHBaum hat geschrieben: Naja .... wenn er schoen schreiben will, sollt er aber eher java nehmen als c++
Ich vermute, dass meinst du nicht wirklich ernst.. ich zähle dich nämlich zu den Mitgliedern hier, welche den Unterschied zwischen einem "Konzept" und einer "Programmiersprache" schon verstanden haben.. :wink:
RHBaum hat geschrieben: Und ne Eventloop ist Overhaed !
"handleData()" wird überhaupt nicht gebremst.. so what?
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Ich vermute, dass meinst du nicht wirklich ernst..
wahrscheinlich reden wir bissi aneinander vorbei :-)
Ob er ne Eventloop brauch, ist IMHO Konzeptsache.
Du versuchst hier die eventloop zu etablieren. Ich bezweifle das er die 2. ueberhaupt brauch. Deshalb ueberhaupt die ganze Disskussion mit Run ueberladen und ableiten usw.
Ich bin der Meinung, das auch die Performance das Konzept beeinflussen sollt. Täte es das nicht, bin ich der Meinung, das c++ die falsche Programmiersprache ist, weil mit anderen Programmiersprachen koennt er Konzepte, egal welche, viel sauberer und effizienter umsetzen.

"handleData()" wird überhaupt nicht gebremst.. so what?
DIe Eventloop an sich ist overhaed. Du weisst schon was da alle im Hintergrund gemacht wird ?
Fuer was braucht er denn die ?

um den thread zu starten ?
um den thread zu beenden ?
das geht recht einfach auch ohne ....
die interne kommunikation geht auch ohne.
Den Thread auf normalen Weg abzuwuergen, geht auch ohne ...
den thread auf boese art abzuwuergen, falls er haengt, hilft dir die eventloop gar ned.
Fuer was braucht er also das ding ???

Einzigste Daseinsberechtigiung hat das Teil an nem Thread, wenn ich simpel Events von dem Mainthread in den anderen Thread mappen will (also Threadwechsel vom main in den anderen Thread per signale/Slots).
Und tut er dass ?

Ciao ...
Mani99
Beiträge: 244
Registriert: 15. April 2009 10:46
Wohnort: München

Beitrag von Mani99 »

RHBaum hat geschrieben: DIe Eventloop an sich ist overhaed. Du weisst schon was da alle im Hintergrund gemacht wird ?
Fuer was braucht er denn die ?

um den thread zu starten ?
um den thread zu beenden ?
das geht recht einfach auch ohne ....
die interne kommunikation geht auch ohne.
Den Thread auf normalen Weg abzuwuergen, geht auch ohne ...
den thread auf boese art abzuwuergen, falls er haengt, hilft dir die eventloop gar ned.
Fuer was braucht er also das ding ???

Einzigste Daseinsberechtigiung hat das Teil an nem Thread, wenn ich simpel Events von dem Mainthread in den anderen Thread mappen will (also Threadwechsel vom main in den anderen Thread per signale/Slots).
Und tut er dass ?

Ciao ...
Jetzt bin ich vollends verwirrt...

Mein gedanke, bzw. unser konzept ist folgendes:

Ob da jetzt Qt sinnvoll ist oder nicht sei dahingestellt, ich kanns mir ohnehin nicht aussuchen!

Auf der einen seite gibt es einen rechner, da läuft der server drauf, und auf der anderen seite z.b. 10 clients (rechner und smartphones).

Vom client wird eine anfrage an den server gesendet, der server registriert das und schiebt die anfrage in einen thread weiter. In dem thread wird die anfrage ausgewertet (berechnungen, printjobs, datenbankabfragen etc.).

Dadurch soll gewährleistet werden, falls neue anfragen reinkommen, diese auch sofort bearbeitet werden.

Mir ist jetzt nicht ganz klar, warum mir dabei threads nicht helfen sollten? Ich meine, von meinem verständnis ausgehend, ist das eigentlich ja genau das was threads machen? Aufgaben m.o.w. parallel durchführen.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

RHBaum hat geschrieben:...weil mit anderen Programmiersprachen koennt er Konzepte, egal welche, viel sauberer und effizienter umsetzen.
Da bin ich anderer Meinung.. aber das ist nicht so wichtig in diesem Foren-Thread..
RHBaum hat geschrieben: DIe Eventloop an sich ist overhaed. Du weisst schon was da alle im Hintergrund gemacht wird ?
Fuer was braucht er denn die ?
Threads dienen nicht dem Selbstzweck: ein Thread soll eine Aufgabe lösen und die Resultate (falls notwendig) wieder zurückliefern. Du wirst vermutlich schon vom Konzept der Kommunikation über Stapel gehört (oder dieses auch schon mal eingesetzt) haben, wo die Hauptapplikation und der Thread die Jobs/Resultate über MT-sichere Stapel austauschen.
Der Vorteil: nur der Stapel muss MT-sicher sein. Es gibt also nur an einem Ort (Q)Mutexe: im "Daten-Austausch-Stapel".

Sieh die Eventloop mal von folgender Seite: die Eventloop IST dieser Stapel. Du brauchst in Qt für den Datenaustausch keine Mutexe: der Eventloop ist der Stapel, die Signals sind in diesem Modell die Jobs respektive deren Antworten.
Das ist extrem anfängerfreundlich (keine Synchronisations-Probleme) und sehr flexibel. Falls du doch keinen Thread brauchst (weil der Job genug schnell ist) lässt du eben "moveToThread()" weg.. und schon hast du eine Single-Threaded-Applikation. Oder du hast einen Threadpool (der Start eines neuen Threads kann ja dauern) und verteilst die Aufträge mit "moveToThread()" bei Bedarf. Das ist schneller als ein von QThread abgeleitetes Objekt zu "starten"..

Probier es mal aus.. das funktioniert super und 90% der Multithreading-Fragen hier im Forum ("warum-wird-Signal-XY-im-falschen-Kontext-ausgeführt") wären hinfällig :wink:
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Mir ist jetzt nicht ganz klar, warum mir dabei threads nicht helfen sollten?
Ich weiss es auch nicht, weil ich dein Konzept nicht kenne.
Deswegen ja auch die Frage, auf was Du Wert legst bei deiner Implementierung. Um was geht es Dir.
- Funktionalitaet des Programmes ?
- Performance ?
- Es mal mit Qt implementiert haben

Alles IMHO valide Motivationen, so ein programm zu schreiben. Aber alle diese Motivationen sollten einen unterschiedlichen einfluss auf das Konzept haben.

2. frage, um was geht es hier, den Server oder Client ? Die haben unterschiedliche Anforderungen, koennte also sein das es durchaus unterschiedliche konzepte gibt.

Performance-Problem iss dabei bissi tiefgruendiger. Mal auf den Server bezogen:
Mal Bezug auf "NetzwerkProgrammierung mit Linux", das Buch mein ich, da werden alle 3 Parallelisierungsarten die fuer Sockets in Frage kommen, verglichen.
- Selectiver Server
- Multithreaded Server mit Pool / ohne Pool
- Multiprocessing server mit Pool / ohne Pool (prefork)

Die Frage was ist Performanter. kann man ned so einfach beantworten. Ausser, dass die entscheidung multithread oder multiprocess nicht von der Performance abhaengig gemacht werden sollte (multiprocessing iss immer kleinwenig langsamer), multiprozessing hat andere Vorteile.
Aber denk mal das faellt hier raus.

Bleibt Selectiver Server vs multithreded.
der Selective server frisst am wenigsten ressourcen
Bei nichtkonkurrierenden anfragen hat er die kuerzesten reaktionszeiten.
Aber sobald mehrere anfragen kommen, gibts quasi ne warteschlange ... das heisst bei nem selektiven server gewinnt immer irgend nen client, waehrend andere quasi warten. Aber das kann man auch in Grenzen halten. Der selektive server ist auch in der summer schneller, wenn der multithreaded server nicht auf mehrer kerne zurueckgreifen kann (vorrausgesetzt man implementiert das multithreading richtig).

Multithreading bringt Dir also bei so nem Server 2 Vorteile:
Nutzung von mehreren Kernen möglich, wenn die Bedingungen stimmen.
Geichmaessigere Aufteilung der ressourcen (rechenzeiten) bei mehreren clients gleichmaessig.

Beantwortet die Frage hoffentlich:
Muss ein Server der mehrere Connections gleichzeitig bedient, undbedingt multithreaded sein ?
Nein !
Die Frage, warum wird multithreading und sockets immer gern beschrieben, und warum sind die meisten Beispiele von "Server" multihreaded ?
Weil Assynchrone socket-programmierung im CStyle den meisten das Gehirn sprengt. Es ist halt ned wirklich intuitiv. Die synchrone programmierung ist viel intuitiver, Aber deren "blockierung" kriegt man nur durch multithreading weg.
Aber die QT bietet Dir halt ne intuitive schnittstelle zur assynchronen programmierung in singlethreadumgebungen an (Signale/Slots).

Also was bleiben weiter fuer Gruende fuer multithreading ?
- du willst mehrere kerne nutzen. Klar.
- du hasst ne zwingend blockierende schnittstelle, willst aber nen nichtblockierendes Interface anbieten.
- Du hasst eine langwierige operation die nicht rational unterbrechen kannst und die lange genug laeuft als das man sie als blockierend betrachten kann, willst aber nen nichtblockierendes Interface anbieten.

mehr eigentlich nicht ...

Wie gesagt, ob Multithreading fuer dich das richtige Konzept ist, entscheiden Deine Anforderung, sollten zumindest.

Selbst mit multithreading gibts mehrere konzepte ...
wieder der Server z.b.:
- ein serverthread, fuer jeden Client gibts ein Thread, Socket(bidirektional) -> DB -> DatenProzesser -> Socket(Antwort) lauft im selben Thread. (der Klassiker -> Datensource -> Senke )
Konsequenz: Die Kommunikation zwischen sever und 1.Client in sich ist zwingend sequentiell (obwohl nen Socket schon bidirektional und duplex sein kann)
oder
- ein serverthread zur verwaltung, fuer jeden client ein sende und ein Empfangssthread, ein Zentraler Thread zur datenverarbeitung, ein thread fuer DB zugriffe. "Wilde" Kommunikation der Threads untereinander.

oder oder ....

Was das beste ist fuer Dich, kommt ganz auf deine Anforderungen an ...

@solarix
wo die Hauptapplikation und der Thread die Jobs/Resultate über MT-sichere Stapel austauschen
Vollkomment klar, die MsgLoop implementiert dir den Nachrichtenkanal threadsicher und an sich ziemlich peroformant.
Macht aber nur sinn wenn du es auch brauchst.
Idealer weisse funtionieren Threads fuer sich ....
du bereitest die daten fuer den Thread auf, du startest den thread. Wenn der Thread fertig ist, gibts ne Nachricht, und der thread beendet sich dann gleich. Die resultate liegen dann an ner vordefinierten stelle.
Damit hasst du genau 3 kommunikations- und Synchronisationspunkte:
den Start, das Ende, und den nen Abbruch mittendrinn, falls notwendig.
das Ende kannst ueber die Msgloop des mainthreads handeln .... die existiert ja eh.
fuer die anderen 2 punkte willst so nen "stapel" einrichten und verwalten (ok, macht Qt fuer dich, aber die kosten hasst trotzdem) ... starten geht automatisch meist ... und fuers abbrechen brauchst eigentlich nur ne atomare variable, oder nen Event oder wenn mies implementierst, ne normale variable mit Mutex geschuetzt...

Bei den oben genannten Modellen ... das lineare Datensink Modell ...
Du hasst NULL kommunikation zwischen den threads. Starten geht ueber den startthread vom der Socketkopie getriggert, das beenden kannst den mainthread ueber seine (die einzige) Loop mitteilen, wenn er eine hat.
das abbrechen geht ueber die Condition , das beenden ueber das kommunikationsprotokoll an sich... warum sollt ich da loops gebrauchen ?

Das "inperformante" an der QTLoop ist der ganze MetaClass mechanismuss, der hintendranhaengt, wenn du nachrichten ueber nen thread hinweg schickst ... damit du nicht nur Simple daten in den Signalen schicken kannst sondern auch komplette strings, maps, Variants ..... und das brauchst du eben nicht zwingend.

Bei dem Konzept mit der "wilden Kommunikation" ueber threadgrenzen hinweg, geb ich dir recht, koennen loops ne richtige Hilfe sein. Da brauchst soweiso einen aehnlichen mechanismus zur Synchronisation!
Solltest aber im Hinterkopf haben, das signale / Slots ueber Threadgrenzen immer ne kopie machen durch den Metaclass Mechanismus (die aber meistens durch implizietes sharing abgefangen wird ^^ )

Ciao ...
Antworten