Я довольно новичок в 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 фактически управляется основным потоком. Я попытался сделать обратное (генерируемый поток посылает сигнал основному потоку), и он работает.
Я думаю, я не понял точно, как работают сигналы, и если это возможно сделать то, что я хотел бы. Есть ли какие-нибудь подсказки об этом? Я смотрел онлайн для решения, но без результата.
Благодаря
Прерывание синхронного кода, как продолжительный цикл через сигнал не будет работать: сигнал/слотам между потоками нужен цикл обработкой событий в приемном потоке (т.е. он должен быть введен в run(), вызвав exec()); для вызова слота принимающий поток должен вернуться в цикл событий; То есть если у вас длинный рабочий цикл, цикл события будет заблокирован, а слот никогда не будет вызываться. –
Думаю, теперь я начинаю понимать лучше. Кстати, я заменил цикл for в файле mythread.run() с помощью app.exec_(). В результате функция myfunc по-прежнему вызывается основным потоком, поэтому я чувствую, что что-то еще не так. – Cell