2014-02-11 109 views
3

我对pyqt非常陌生,所以我希望在我试图做的事情中不会有什么奇怪的。我试图通过使用PyQt信号来创建QThreads之间的交互。特别是,我想要做的是从一个线程发出一个信号,这个信号应该中断线程正在执行的特定方法。顺便说一下,我遇到了一些问题,所以我想知道我想要做的是合法的。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

我想我现在开始理解得更好了。顺便说一下,我用app.exec_()替换了mythread.run()中的for循环。结果是函数myfunc仍然被主线程调用,所以我觉得别的是错的。 – Cell

回答

0

好了,从我能明白的是,你想要的线程进入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