Threads nacheinander ausführen - geht das eleganter?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
blck
User
Beiträge: 11
Registriert: Sonntag 17. Juli 2011, 00:37

Hallo,
ich bin zurzeit dabei mich in das Thema Threading einzuarbeiten. Konkret arbeite ich an einem Offline-RSS-Reader. Dazu hab ich eine Update-Routine geschrieben, die verschiedene Update-Möglichkeiten (Alle Seiten / Eine Seite - Alle Kategorien / Eine Seite - Eine Kategorie) durchgeht. Die letzten beiden Punkte sind kein Problem, weil ich da immer nur einen Vorgang habe (also zum Beispiel die Funktion, die die Kategorien abruft), denn es ist eine Funktion und kein Thread. Nun zu meinem eigentlichen Problem:

Wenn ich jetzt alle Seiten aktualisiere (das geschieht in einem Thread, damit die Benutzeroberfläche nicht einfriert). Da es sich aber um Threads handelt, kann ich nicht einfach sagen Seite1.begin(), Seite2.begin().... da dann Python abstürzt wegen Überforderung :wink:
Deswegen überprüfe ich derzeit in if-Abfragen, ob der vorige Thread fertig ist und rufe dann den nächsten Thread auf. Da ich aber nicht immer alle Seiten aktualisieren will (weil der Nutzer sie beispielsweise deaktiviert hat) ist dieser Weg schlecht, aber der einzige der mir einfiel :mrgreen: Dass die Seiten aufgerufen werden, ist zwar nicht schlimm, da die Kategorien von der Funktion nicht aktualisert werden, weil ich alle Kategorien der Seite deaktiviere, aber der Aufruf ist halt umsonst und umständlich, wenn ich das Programm von derzeit 4 Seiten auf x-Seiten erhöhen will.

Als Code sieht der fragliche Abschnitt derzeit so aus:

Code: Alles auswählen

def update(self):
....
        if (fenster.ui.stackedWidget.currentIndex() == 0) and (kategorie == "none"):
                starteSpiegel()
# Alle Seiten werden geupdatet, die erste Funktion wird aufgerufen, siehe weiter unten:
...

def starteSpiegel():
  from setupSpiegel import updateSpiegelall
  update_spiegel = updateSpiegelall("none","none")
  update_spiegel.begin()
  fenster.connect(update_spiegel, SIGNAL("finished()"), starteNTV)

def starteNTV():
  from setupNTV import updateNTVall
  update_ntv = updateNTVall("none","none")
  update_ntv.begin()
  fenster.connect(update_ntv, SIGNAL("finished()"), starteEngadget)

def starteEngadget():
  from setupEngadget import updateEngadgetall
  update_engadget = updateEngadgetall("none","none")
  update_engadget.begin()
  fenster.connect(update_engadget, SIGNAL("finished()"), starteMeego)

def starteMeego():
  from setupMeego import updateMeegoall
  update_meego = updateMeegoall("none","none")
  update_meego.begin()
  fenster.connect(update_meego, SIGNAL("finished()"), zeigeFertig)

def zeigeFertig():
  fenster.ui.stackedWidget.setCurrentIndex(6)

Es wäre toll eine Liste mit Seiten erstellen zu können und dann per exec() auszuführen und beispielsweise so aussieht (Spiegel, engadget, ...) und dann das ganze irgendwie so aufzurufen exec(liste+".begin") und damit den Thread zu starten und erst wenn der fertig ist, den Zeiger in der Liste zu erhöhen und weiter zu machen.

Ich hoffe ich hab genug Infos geliefert, damit ihr mir helfen könnt.

MfG blck
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

also wenn ich das ganze richtig verstanden habe, dann sollte es doch funktionieren, wenn du in dem separatem Thread über die Liste der zu aktualisierenden Seiten iterieren würdest und du das nächste Element des Iterators (=die nächste Seite) erst abrufst, wenn der Abruf der vorhergehenden abgeschlossen ist.

Alternativ sollte es auch funktionieren, wenn du alle Jobs in ein Framework wie Celery schiebst, dass die Sache dann für die Asynchron im Hintergrund macht. Erfahrung habe ich damit aber selber keine.

Gruß, noisefloor
blck
User
Beiträge: 11
Registriert: Sonntag 17. Juli 2011, 00:37

Hallo noisefloor,
danke für deine Vorschläge. Das mit dem Framework ist leider nicht möglich, da ich das Programm für maemo5 entwickele.
Die Idee mit dem Thread hatte ich auch, aber selbst dann müsste ich die Liste ja noch aufbauen und ausführen. Das aufbauen ist kein Problem, aber wie führe die Listenelemente dann aus? Geht das wirklich mit exec(Name+".begin")?

MfG blck
BlackJack

@blck: Ich glaube erst einmal nicht das Python bei mehreren Threads wegen Überforderung abstürzt. Insbesondere nicht wenn es sich hier wirklich nur um vier Threads handelt. Es ist wahrscheinlicher, dass Du in den Threads etwas tust was nicht „thread safe“ ist. Oder das Du Qt grundsätzlich nicht richtig verwendest. Da könnte dann aber Python nichts dafür.

Du könntest einen `QThreadPool` erstellen und den mit den Aufgaben füttern die erledigt werden sollen. `QtCore::QtConcurrent` scheint bei den Python-Anbindungen die ich hier installiert habe (PyQt4 von Ubuntu 10.04 und aktuelles PySide) noch nicht angekommen zu sein. Das wäre vielleicht noch einmal etwas schöner als sich mit Threads herum zu schlagen.

Das mit ``exec`` ist ein Scherz oder? Wozu soll dass denn gut sein? Vergiss bitte dass es ``exec`` gibt. Statt den Namen in die Liste zu stecken solltest Du einfach das Objekt in die Liste stecken.
Antworten