2017-05-27 2 views
1

Ich versuche, einen Thread für eine GUI zu erstellen, die eine lang laufende Funktion umschließt. Mein Problem ist also in Bezug auf PyQt und QThreads formuliert, aber ich stelle mir vor, dass das gleiche Konzept auch für Standard-Python-Threads gelten könnte, und würde im Allgemeinen alle Vorschläge begrüßen.Beenden eines QThread, der eine Funktion umschließt (d. H. Ein Flag "wills_to_end" kann nicht abgefragt werden)

Typischerweise wird ein Thread zu ermöglichen verlassen wird beim Laufen, verstehe ich eine „wants_to_end“ -Kennzeichen, dass einschließlich, die in dem Thread periodisch überprüft Praxis gut ist - zB:

Pseudocode (in my thread): 
def run(self): 
    i = 0 
    while (not self.wants_to_end) and (i < 100): 
     function_step(i) # where this is some long-running function that includes many streps 
     i += 1 

Doch wie meine GUI ist, eine vor-geschriebene lang laufende Funktion zu wickeln, ich kann nicht einfach solch eine "wills_to_end" -Flagabstimmung in den lang laufenden Code einfügen.

Gibt es eine andere Möglichkeit, meinen Worker-Thread zwangsweise von meiner Haupt-GUI zu beenden (d. H., Ich kann eine Schaltfläche in die GUI einfügen, um die Verarbeitung zu stoppen)?

Mein einfaches Beispiel Fall ist:

class Worker(QObject): 
    finished = pyqtSignal() 

    def __init__(self, parent=None, **kwargs): 
     super().__init__(parent) 
     self.kwargs = kwargs 


    @pyqtSlot() 
    def run(self): 
     result = SomeLongComplicatedProcess(**self.kwargs) 
     self.finished.emit(result) 

mit der Nutzung in meinem Mainwindow GUI:

self.thread = QThread() 
    self.worker = Worker(arg_a=1, arg_b=2) 
    self.worker.finished.connect(self.doSomethingInGUI) 
    self.worker.moveToThread(self.thread) 
    self.thread.started.connect(self.worker.run) 
    self.thread.start() 

Antwort

1

Wenn die lang andauernde Funktionsbausteine, die einzige Möglichkeit, mit Gewalt den Faden über seine stoppen terminate() Methode (es kann auch notwendig sein, auch wait() anzurufen). Es gibt jedoch keine Garantie, dass dies wird immer funktionieren, und die docs sagen, auch die folgenden:

Warnung: Diese Funktion ist gefährlich, und seine Verwendung wird abgeraten. Der Thread kann an jedem Punkt in seinem Codepfad beendet werden. Threads können beim Ändern von Daten beendet werden. Es gibt keine Chance für den Thread nach sich aufzuräumen, eventuell gehaltene Mutexe freizuschalten usw. Kurz gesagt, nutze diese Funktion nur wenn unbedingt nötig.

A viel sauberer Lösung ist, einen separaten Prozeß zu verwenden, anstatt einen separaten Thread. In Python könnte dies die Verwendung des Moduls multiprocessing bedeuten. Aber wenn Sie damit nicht vertraut sind, könnte es einfacher sein, die Funktion als Skript über QProcess auszuführen (das Signale bereitstellt, die eine einfachere Integration mit Ihrer GUI ermöglichen sollten). Sie können dann einfach den Worker-Prozess bei Bedarf kill() bearbeiten. Allerdings, wenn diese Lösung irgendwie unbefriedigend ist, gibt es viele andere IPC approaches, die Ihren Anforderungen besser entsprechen könnten.

+0

Vielen Dank für diese Antwort. Ich habe versucht, zu beenden(), aber der Thread lief einfach weiter! Es klingt wie Multiprocessing ist ein guter Weg nach vorne. Ich werde jetzt die Dokumente studieren, aber wenn Sie ein Mindestarbeitsbeispiel haben, wäre das auch großartig! Vielen Dank. – PhysLQ

+1

@PhysLQ. Für ein einfaches Beispiel siehe [diese Antwort] (https://stackoverflow.com/a/40093862/984421). – ekhumoro

+0

Danke. Ist es besser, Multiprocessing oder QThread hier zu benutzen, findest du? Ich bin mit beiden vertraut, werde aber beide sehen. – PhysLQ

Verwandte Themen