2014-02-11 6 views
3

Я довольно новичок в pyqt, поэтому надеюсь, что ничего не будет странно в том, что я пытаюсь сделать. Я пытался создать взаимодействие между QThreads с помощью сигналов PyQt. В частности, то, что я хотел бы сделать, это испустить сигнал из потока, и этот сигнал должен прерывать то, что поток выполняет для запуска определенного метода. Кстати, у меня проблемы с этим, поэтому я задаюсь вопросом, законно ли то, что я пытаюсь сделать.PyQt: прерывание qthread через сигналы

К примеру, сейчас я пытался сделать что-то вроде этого:

import sys 
import time 
from PyQt4 import QtGui as qt 
from PyQt4 import QtCore as qtcore 
from PyQt4.QtCore import QThread 
import threading 

app = qt.QApplication(sys.argv) 
class widget(qt.QWidget): 

    def __init__(self, parent=None): 
     qtcore.QObject.__init__(self) 


    def appinit(self): 
     self.mysignal = qtcore.SIGNAL("mysignal") 
     thread = mythread(self) 
     thread.start() 
     time.sleep(5) 
     print "before emit",str(threading.current_thread()) 
     self.emit(self.mysignal,"hello, I'm thread "+str(threading.current_thread())) 
     print "after emit",str(threading.current_thread()) 



class mythread(QThread): 
    def __init__(self,parent): 
     qtcore.QThread.__init__(self, parent=app) 
     self.parent=parent 

    def run(self): 
     self.mysignal = qtcore.SIGNAL("mysignal") 
     self.connect(self.parent, self.mysignal, self.myfunc) 
     for i in range(15): 
      print "**",threading.current_thread(),i 
      time.sleep(1) 

    def myfunc(self, msg): 
     print threading.current_thread(), msg, "Enter" 
     time.sleep(5) 
     print threading.current_thread(), msg, "Exit" 


def main(): 
    mywidget = widget() 
    mywidget.show() 
    qtcore.QTimer.singleShot(0, mywidget.appinit) 
    sys.exit(app.exec_()) 

main() 

Выход я получаю:

** <_DummyThread(Dummy-1, started daemon 1968)> 0 
** <_DummyThread(Dummy-1, started daemon 1968)> 1 
** <_DummyThread(Dummy-1, started daemon 1968)> 2 
** <_DummyThread(Dummy-1, started daemon 1968)> 3 
** <_DummyThread(Dummy-1, started daemon 1968)> 4 
before emit <_MainThread(MainThread, started 2928)> 
<_MainThread(MainThread, started 2928)> hello, I'm thread <_MainThread(MainThread, started 2928)> Enter 
** <_DummyThread(Dummy-1, started daemon 1968)> 5 
** <_DummyThread(Dummy-1, started daemon 1968)> 6 
** <_DummyThread(Dummy-1, started daemon 1968)> 7 
** <_DummyThread(Dummy-1, started daemon 1968)> 8 
** <_DummyThread(Dummy-1, started daemon 1968)> 9 
<_MainThread(MainThread, started 2928)> hello, I'm thread <_MainThread(MainThread, started 2928)> Exit 
after emit <_MainThread(MainThread, started 2928)> 
** <_DummyThread(Dummy-1, started daemon 1968)> 10 
** <_DummyThread(Dummy-1, started daemon 1968)> 11 
** <_DummyThread(Dummy-1, started daemon 1968)> 12 
** <_DummyThread(Dummy-1, started daemon 1968)> 13 
** <_DummyThread(Dummy-1, started daemon 1968)> 14 

Я бы на самом деле ожидал MyThread прервать его выполнение и запустить MyFunc. Кстати, mythread не прерывает его выполнение, а функция myfunc фактически управляется основным потоком. Я попытался сделать обратное (генерируемый поток посылает сигнал основному потоку), и он работает.

Я думаю, я не понял точно, как работают сигналы, и если это возможно сделать то, что я хотел бы. Есть ли какие-нибудь подсказки об этом? Я смотрел онлайн для решения, но без результата.

Благодаря

+2

Прерывание синхронного кода, как продолжительный цикл через сигнал не будет работать: сигнал/слотам между потоками нужен цикл обработкой событий в приемном потоке (т.е. он должен быть введен в run(), вызвав exec()); для вызова слота принимающий поток должен вернуться в цикл событий; То есть если у вас длинный рабочий цикл, цикл события будет заблокирован, а слот никогда не будет вызываться. –

+0

Думаю, теперь я начинаю понимать лучше. Кстати, я заменил цикл for в файле mythread.run() с помощью app.exec_(). В результате функция myfunc по-прежнему вызывается основным потоком, поэтому я чувствую, что что-то еще не так. – Cell

ответ

0

Ok, от того, что я мог бы понять, что вы хотите, чтобы нить, чтобы ввести 5-секундный сон, прежде чем он перебирает дальше.

import sys 
import time 
from PyQt4 import QtGui as qt 
from PyQt4 import QtCore as qtcore 
from PyQt4.QtCore import QThread 
import threading 

app = qt.QApplication(sys.argv) 
class widget(qt.QWidget): 

    def __init__(self, parent=None): 
     qtcore.QObject.__init__(self) 


    def appinit(self): 
     self.mysignal = qtcore.SIGNAL("mysignal") 
     thread = mythread(self,self.mysignal) 
     thread.start() 
     time.sleep(5) 
     print "before emit",str(threading.current_thread()) 
     self.emit(self.mysignal,"hello, I'm thread "+str(threading.current_thread())) 
     print "after emit",str(threading.current_thread()) 



class mythread(QThread): 
    def __init__(self,parent,sig): 
     qtcore.QThread.__init__(self, parent=app) 
     self.parent=parent 
     self.mysignal = sig 
     self.stop_event=threading.Event() 
     self.connect(self.parent, self.mysignal, self.setIt) 

    def run(self): 

     for i in range(15): 
      if self.stop_event.isSet(): 
       self.myfunc() 
      print "**",threading.current_thread(),i 
      time.sleep(1) 

    def setIt(self,msg): 
     self.stop_event.set() 
     self.msg = msg 

    def myfunc(self): 
     print threading.current_thread(),self.msg , "Enter" 
     time.sleep(5) 
     print threading.current_thread(),self.msg , "Exit" 
     self.stop_event.clear() 


def main(): 
    mywidget = widget() 
    mywidget.show() 
    qtcore.QTimer.singleShot(0, mywidget.appinit) 
    sys.exit(app.exec_()) 

main() 

Выход:

** <_DummyThread(Dummy-1, started daemon 7312)> 0 
** <_DummyThread(Dummy-1, started daemon 7312)> 1 
** <_DummyThread(Dummy-1, started daemon 7312)> 2 
** <_DummyThread(Dummy-1, started daemon 7312)> 3 
** <_DummyThread(Dummy-1, started daemon 7312)> 4 
before emit <_MainThread(MainThread, started 232)> 
after emit <_MainThread(MainThread, started 232)> 
<_DummyThread(Dummy-1, started daemon 7312)> hello, I'm thread <_MainThread(MainThread,  started 232)> Enter 
<_DummyThread(Dummy-1, started daemon 7312)> hello, I'm thread <_MainThread(MainThread,  started 232)> Exit 
** <_DummyThread(Dummy-1, started daemon 7312)> 5 
** <_DummyThread(Dummy-1, started daemon 7312)> 6 
** <_DummyThread(Dummy-1, started daemon 7312)> 7 
** <_DummyThread(Dummy-1, started daemon 7312)> 8 
** <_DummyThread(Dummy-1, started daemon 7312)> 9 
** <_DummyThread(Dummy-1, started daemon 7312)> 10 
** <_DummyThread(Dummy-1, started daemon 7312)> 11 
** <_DummyThread(Dummy-1, started daemon 7312)> 12 
** <_DummyThread(Dummy-1, started daemon 7312)> 13 
** <_DummyThread(Dummy-1, started daemon 7312)> 14 
Смежные вопросы