QThread: QThread::finished() blockiert QThread::terminated()

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
root_tux_linux
User
Beiträge: 36
Registriert: Sonntag 16. Dezember 2007, 04:18

Hi

Ich hab ein kleines Problem und zwar überlagert das "finished" Signal das "terminated" Signal des QThread.

Wenn ich nun auf Abort drücke, wird der Thread mit QThread::terminate() abgeschossen, aber das Signal finished() und terminated() ausgelöst, wobei das finished() Signal, terminated() überlagert und deshalb dann die Funktion self.onFinish() ausgelöst wird anstelle von self.onAbort().

Kann man das irgendwie zurecht biegen? :/


Btw. Wenn ich die Zeile "self.connect(self.thread, QtCore.SIGNAL('finished()'), self.onFinish)" auskommentiere funzt das terminated() Signal wie es sollte :/

Code: Alles auswählen

        # Signal and Slots for QThread
        self.connect(self.buttonBox.button(QtGui.QDialogButtonBox.Abort), QtCore.SIGNAL('clicked()'), self.thread.terminate)
        self.connect(self.thread, QtCore.SIGNAL('terminated()'), self.onAbort)
        self.connect(self.thread, QtCore.SIGNAL('finished()'),  self.onFinish)
        self.thread.dataWritten.connect(self.progressBar.setValue)
        self.thread.currentPass.connect(self.labelPasses.setText)
            
    def onAbort(self):
        self.progressBar.setValue(self.size)
        self.progressBar.setFormat('Aborted')

    def onFinish(self):
        self.progressBar.setValue(self.size)
        self.progressBar.setFormat('succsessfully completet')

class Thread(QtCore.QThread):
    dataWritten = QtCore.pyqtSignal(int)
    currentPass = QtCore.pyqtSignal(str)
    
    def __init__(self, algo, device,  size):
        QtCore.QThread.__init__(self)
        self.algo = algo
        self.device = device
        self.size  = size
      
    def run(self):
        stat = 0
        f = open(self.device,  'wb')
        
        for method in self.algo:
            if method == 'random':
                data = urandom(1000)
            else:
                data = method * 256
                
            for i in xrange(self.size): # not Python 3000 compatible (range)
                f.write(data)
                self.dataWritten.emit(i)
            f.seek(0)
            stat +=1
            self.currentPass.emit(str(stat)+'/'+str(len(self.algo))) 

        f.close()
AMD Athlon 64 X2 6000+, ASUS M2N-SLI Deluxe, ASUS EN8600GTS Silent, 4GB Apacer DDR2 800Mhz | Gentoo Linux x86_64
AMD Sempron 2500+, MSI KT4, ASUS N6200, 2x 512MB Apacher DDR 400Mhz, Hauppauge PVR150 | Arch Linux i686
### Sorry for my bad english ###
lunar

Das ".terminate()"-Signal „funzt“ auch, nur wird es wahrscheinlich vor ".finished()" ausgelöst, und im Slot zu ".finished()" werden die vorherigen Werte überschrieben. Du musst Dir in ".onAbort()" eben merken, dass der Thread gewaltsam abgebrochen wurde, und die Anweisungen in ".onFinish()" nur ausführen, wenn dem nicht so war.

Wenn Du die neue Syntax bereits zur Deklaration der Signale nutzt, dann kannst Du sie auch beim Verbinden nutzen (e.g. "self.thread.finished.connect(self.onFinish)").

Die Warnung in der Dokumentation von "QThread.terminate()" ist im Übrigen nicht zum Scherz da, von der Verwendung von ".terminate()" wird dringend abgeraten. Diese Funktion ist nicht dazu da, einen „Abbrechen“-Knopf zu implementieren.
root_tux_linux
User
Beiträge: 36
Registriert: Sonntag 16. Dezember 2007, 04:18

lunar hat geschrieben:Diese Funktion ist nicht dazu da, einen „Abbrechen“-Knopf zu implementieren.
Wie dann?

Wenn ich mit self.exec_() ne eigene Eventschleife aufbaue und dann mittels self.exit() den Thread von innen beenden will läuft der Sack weiter.
AMD Athlon 64 X2 6000+, ASUS M2N-SLI Deluxe, ASUS EN8600GTS Silent, 4GB Apacer DDR2 800Mhz | Gentoo Linux x86_64
AMD Sempron 2500+, MSI KT4, ASUS N6200, 2x 512MB Apacher DDR 400Mhz, Hauppauge PVR150 | Arch Linux i686
### Sorry for my bad english ###
lunar

Üblicherweise, indem Du regelmäßig auf eine Abbruchbedingung prüfst (Beispiel).

Zu Deinem Problem mit ".exec_()" und ".exit()" kann man ohne Quelltext nichts sagen.
Antworten