Seite 1 von 1

QThread + QNetworkAccessManager + EventLoop

Verfasst: 4. April 2009 00:04
von tomf
Habe folgendes Szenario:

Es gibt einen "LoaderThread" der im Hintergrund Bilder ladet. Derzeit hat der eine run() Methode in der er solange läuft solange ein Stack mit Bildern die er laden soll voll ist. Ist nichts mehr drinnen geht er schlafen. Sind neue Bilder zum Laden da wird er aufgeweckt, ladet die und schickt bei jedem Bild ein Signal raus, dass das Bild fertig ist.

Das ganze funktioniert wunderbar. Nur möchte ich diesen gerne erweitern, damit er auch Bilder aus dem Netz laden kann. Im Prinzip soll er einfach statt QImage::load ein QNetworkAccessManager::get aufrufen. Wenn dann das finished Signal kommt soll er das Bild aus dem QNetworkReply holen, und dann sein Signal schicken, dass das Bild fertig ist.

Das Problem an der Sache ist jetzt aber, dass ich anscheinend keine Signals im Thread empfangen kann (also keine Slots) solange ich keinen EventLoop laufen habe. Ich muss also QThread::exec aufrufen. So und jetzt steig ich aus. Verstehe ich das richtig, dass ich dann den Thread NUR mehr via Signals/Slots steuern kann? Ich kann den Thread dann nicht mehr in einem "Loop" laufen lassen und auch nicht mehr eigenhändig schlafen legen?

Falls ich das richtig verstehe: kann ich den EventLoop auch auf andere Weise verwenden - also ohne immer nur auf Events zu warten?

Kurz und bündig würd ich gerne einen Thread haben der in einer Schleife Dinge abarbeitet solange er was zu tun hat. Wenn nicht soll er schlafen gehen. Nur soll er auch Signals empfangen (Slots verarbeiten) :)

Hoffe das versteht jemand :)

Verfasst: 4. April 2009 08:18
von upsala
Da ein ProcessEvents mit dem Thread eigenen QEventLoop so nicht möglich ist, würde ich die event-Routine immer laufen lassen und per QTimer eine Methode aufrufen um deinen Stack abzuarbeiten (einzeln, nicht alle auf einmal)

Verfasst: 4. April 2009 22:22
von tomf
upsala hat geschrieben:Da ein ProcessEvents mit dem Thread eigenen QEventLoop so nicht möglich ist, würde ich die event-Routine immer laufen lassen und per QTimer eine Methode aufrufen um deinen Stack abzuarbeiten (einzeln, nicht alle auf einmal)
Thx - habs jetzt mehr oder weniger so gemacht. Jedesmal wenn ein Bild zum Stack hinzugefügt wird wird überprüft ob der Thread schläft. Wenn ja wird er via Signal geweckt (Singleshot 0ms Timer) und die Methode die die Bilder ladet/verarbeitet schaut am Ende ob weitere Bilder im Stack sind und ruft sich selbst wieder via Singleshot 0ms Timer auf.

Ein kleines Problem hab ich noch: der QNetworkAccessManager erstellt ja auch einen eigenen Thread (sieht zumindest so aus) und wenn mein Thread vorher beendet wird bevor der "Netzwerkthread" beendet wird krieg ich ein nettes Assert. Das komische daran ist aber, dass bevor der "Netzwerkthread" beendet wird aber bereits alles erledigt wurde. Kleines Ablaufmodell:

1. QNetworkAccessManager.get
2. finished(QNetworkReply*)
3. emit zu meinem "LoaderThread" dass das Bild aus dem Netz geholt wurde
4. Bild wird verabeitet -> für mich ist eigentlich alles erledigt
5. mein LoaderThread wird beendet weil zb. das Programm geschlossen wird
6. erst jetzt beendet sich der "Netzwerkthread" und liefert ein Assert weil er den Slot nicht findet bzw. die Meldung ist, dass man keine Slots aus anderen Threads aufrufen kann oder so. Das komische ist aber, dass schon alles fertig abgearbeitet wurde...

Weiss jemand was es da hat?