2016-05-09 12 views
2

Ich würde gerne wissen, wie man einen QThread pausiert und dann wieder aufnimmt, wenn ich ein Signal bekomme. Ich habe gelesen und weiß, dass ich etwas tun kann:Unterbrechung von QThread Schlaf

def run(self): 
    ... 
    self.ready=False 
    while not self.ready: 
     self.sleep(1) 
    ... 
... 
@QtCore.Slot() 
def set_ready(self): 
    self.ready = True 

Aber was ich tun möchte, ist die Abfrage im Thread zu vermeiden. Ich möchte den Schlaf nicht auf eine kurze Zeit einstellen müssen und weiter überprüfen. Ich möchte schlafen gehen, bis ich ein Signal von meinem Hauptfaden bekomme, um fortzufahren.

Was ich in meinem Thread tue, ist dies:

(pseudo code) 
with open file: 
    read a block of data 
    while data: 
     sendThread = send the block via UDP 
     read the next block of data 
     while not ready or sendThread.isRunning: 
      sleep(0.1) 

In meinem Haupt-Thread ich Setup eine QtNetwork.QUdpSocket readyread ein Verfahren zu verbinden eingehende Datagramme zu behandeln und zu dekodieren. Wenn es die Antwort bekommt, auf die ich warte, sendet es ein Signal an den set_ready Slot, um dem Thread mitzuteilen, dass er ein anderes Datagramm senden soll. Ich weiß nicht immer, wie lange es dauert, bis das andere System reagiert, obwohl ich wahrscheinlich einen langen Timeout-Wert von 30 Sekunden oder so haben werde.

Gibt es eine Möglichkeit, den Schlaf des Threads zu unterbrechen? so konnte ich so etwas tun:

sleep(30) 
if not ready: 
    Timeout occurred stop processing 
else: 
    Continue processing. 

Antwort

2

du leicht die Arbeiter Muster mit recht tun können von QThreads verwenden. Es gibt eine example in der QThread Dokumentation. Der genaue Code wird ein wenig anders sein, abhängig davon, ob Sie PyQt oder PySide verwenden (es sieht so aus, als ob Sie PySide aus Ihrem Beispiel verwenden).

Ein bemerkenswertes Problem mit PySide im Vergleich zu PyQt ist, dass they didn't wrap QtCore.Q_ARG, so in PyQt, wo Sie normalerweise QMetaObject.invokeMethod einen Schlitz zu nennen (mit Argumenten) auf das Worker Objekt aus dem Haupt-Thread verwenden könnten, kann man nicht direkt tun können, in PySide und müssen einen Dummy Signal (dh. Main.send_signal) erstellen, um mit dem Steckplatz auf dem Arbeiter zu verbinden, so dass Sie es aus dem Hauptthread aufrufen können.

import time 
import sys 
from PySide import QtCore, QtGui 


class Worker(QtCore.QObject): 

    send_signal = QtCore.Signal(str) # using PySide 
    # QtCore.pyqtSignal(str) ## using PyQt 

    # @QtCore.pyqtSlot(str) 
    @QtCore.Slot(str) 
    def receive_slot(self, data): 
     # data could be a filepath 
     # open file 
     # ... do stuff 
     # close file 
     QtCore.QThread.sleep(1) # to simulate doing stuff 
     self.send_signal.emit(data + ' success') 


class Main(QtGui.QWidget): 

    send_signal = QtCore.Signal(str) 

    def __init__(self): 
     super(Main, self).__init__() 
     self.worker = Worker() 
     self.thread = QtCore.QThread(self) 
     self.worker.moveToThread(self.thread) 
     self.worker.send_signal.connect(self.receive_slot) 
     self.send_signal.connect(self.worker.receive_slot) 
     self.thread.start() 
     self.send_signal.emit('Start') 

    @QtCore.Slot(str) 
    def receive_slot(self, data): 
     print 'Main: {}'.format(data) 
     self.send_signal.emit('Message {}'.format(time.time())) 


if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    window = Main() 
    window.show() 
    app.exec_() 
+0

Ich bin ziemlich neu zu Thread-Programmierung, also ertragen Sie mit mir. Ich habe meine Dateiverarbeitung in einen separaten Thread verschoben, weil sie die GUI aufhängt und ich möchte dem Benutzer erlauben, den Prozess "abzubrechen". Wie öffne ich die Datei mit Ihrem Beispiel? Normalerweise mache ich das mit 'open' (Dateiname, 'rb') als binaryFile: 'methodology. Ist das überhaupt möglich, oder muss ich die Datei öffnen, wenn der 'QThread' läuft, dann schließe sie bei Beendigung? Ich möchte sicherstellen, dass die Datei ordnungsgemäß geschlossen wird. Ich denke, ich würde die Datei auf "__init__" öffnen und die Verarbeitung im 'slot' vornehmen und dann schließen, wenn der Thread endet? –

+0

Möchten Sie die Datei wirklich die ganze Zeit offen halten? Kannst du einfach die ganze Datei im Speicher lesen und dann schließen? Es ist möglich, die Datei zu öffnen, einige Operationen auszuführen und sie später zu schließen, aber Sie können die Operation nicht mitten in einem 'mit'-Kontext anhalten, ohne auch die Hauptthread-Ereignisschleife anzuhalten (wodurch die GUI eingefroren wird). Kannst du einfach den gesamten Vorgang, einschließlich Dateieröffnung **, in den Worker-Thread verschieben? Auf diese Weise gibt es keinen Grund, weiterhin Daten zwischen Haupt- und Worker-Thread hin- und herzusenden. –

+0

Das Problem ist, dass die Datei auf der großen Seite ist, ich denke, ich könnte das Ganze in den Speicher laden. Eines der Probleme, die ich versuche, ist, dass das Programm, das ich ersetze (in Java geschrieben), lange braucht, um die Datei zu laden, bevor der Benutzer sie verarbeiten kann. Also habe ich versucht, das zu vermeiden, indem ich Chunks auf einmal zur Verarbeitung geladen habe. Ich sollte sehen, wie viel Zeit ich bekomme, wenn ich die Datei vollständig lade. –