Ich versuche, Aufgaben hinter einem GUI zu automatisieren. Meine GUI hat mehrere Tasten, die bestimmte Funktionen starten sollen, und eine Taste, um jede laufende Funktion zu stoppen. Wenn eine Funktion ausgeführt wird, sind alle Schaltflächen außer der Schaltfläche "Abbrechen" ausgegraut. Ich brauche den zusätzlichen Thread, damit meine GUI noch reagiert, während die langen Funktionen laufen.Dekorateur für zusätzlichen Thread
Jetzt möchte ich einen Dekorateur implementieren, um diese Funktionen zu dekorieren. Dieser Dekorator sollte die Funktion in einem separaten Thread ausführen. Wenn der Benutzer die Abbruchtaste drückt, sollte die Funktion in diesem zusätzlichen Thread eine Art Stoppsignal empfangen, das die eingerichtete Funktion verwenden kann, um ihre aktuelle Aufgabe zu beenden und zu beenden.
Ich weiß, dass es möglich ist, eine Klasse des Typs threading.Thread für jede Funktion zu implementieren und die aktuelle Funktion als "def run (self):" einzufügen, aber es scheint nicht wie eine elegante Lösung.
Gibt es einen Weg? Für mich scheint es ein häufiges Problem zu sein, aber ich habe keine Lösung über Google gefunden, außer um die Funktionen als Klassen zu schreiben und diese als separate Threads auszuführen.
Bearbeiten 1:
Lassen Sie mich ein paar Beispiele hinzufügen. Gerade jetzt sehen meine Funktionen wie folgt aus:
def function1:
function_code
Aber wenn ich Klassen schaffen würde es so aussehen:
class class1(threading.Thread):
stopper = None
def __init__(self):
init_code
def run(self):
function_code
def function1:
t = class1()
t.stopper = some_stop_condition
t.run()
Der zweite Code ist viel länger und braucht eine Klasse und eine Funktion für jede Taste. Es erscheint einfach viel komplizierter und ich hoffe es ist unnötig.
Bin ich falsch oder mache ich etwas falsch?
Edit 2:
Mein neuer Kodex nach großartigem Beispiel des salomonderossi:
def run_async(func):
@functools.wraps(func)
def async_func(*args, **kwargs):
queue = Queue.Queue()
t = threading.Thread(target=func, args=(queue,) + args, kwargs=kwargs)
t.start()
return queue, t
return async_func
# @layout_decorators.runInSeparateThread()
@run_async
def test2(myQueue):
print "executing test2"
import time
for k in range(6):
print k
try:
myQueue.get(False)
except Queue.Empty:
print "cancelled"
return
time.sleep(1)
def test22():
print "executing test22"
global globalQueue
globalQueue, t = test2()
if __name__ == "__main__":
import time
print "\n\n"
test22()
time.sleep(2)
globalQueue.put("stop")
Aber es stoppt den Faden an der ersten Chance. Auch wenn ich die letzte Zeile entfernen (was ich dachte, stoppt den Faden) meine Ausgabe
executing test22
executing test2
0
cancelled
Warum ist die Klasse 'threading.Thread' keine elegante Lösung? – qvpham
@AlexHall: Ich will es nicht töten, ich will die Funktion das Haltesignal handhaben und von selbst verlassen. – Stefan
@julivico: Weil ich müsste 5 Klassen statt 5 Funktionen und einen Dekorateur schreiben. Diese Klassen wären bis auf die interne run-Funktion identisch. Ich weiß, dass ich von einem von ihnen erben könnte und die Lauf-Funktion für jeden von ihnen ändern könnte. Scheint immer noch zu kompliziert für diese scheinbar einfache Aufgabe. – Stefan