Не могу понять, почему несмотря на mutex.lock(), потоки все равно выполняют один и тот же кусок кода одновременно. Есть диалоговое окно, которое по запросу потока должно появляться и позволять пользователю ввести сообщение. Когда сообщение введено и нажата кнопка "ОК", это сообщение должно быть получено этим самым потоком. Вот код:
class MyDialog(QtGui.QDialog):
got_message = QtCore.pyqtSignal("QString")
def __init__(self, *args, **kwargs):
super(MyDialog, self).__init__(*args, **kwargs)
self.setModal(True)
self.message_label = QtGui.QLabel(u"Message")
self.message_input = QtGui.QLineEdit()
self.dialog_buttons = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
self.dialog_buttons.accepted.connect(self.accept)
self.dialog_buttons.rejected.connect(self.reject)
self.dialog_buttons.accepted.connect(self.on_accepted)
self.hbox = QtGui.QHBoxLayout()
self.hbox.addWidget(self.message_label)
self.hbox.addWidget(self.message_input)
self.vbox = QtGui.QVBoxLayout()
self.vbox.addLayout(self.hbox)
self.vbox.addWidget(self.dialog_buttons)
self.setLayout(self.vbox)
self.input_finished = QtCore.QWaitCondition()
@QtCore.pyqtSlot()
def show_input(self):
print "showing input"
self.show()
self.setModal(True)
@QtCore.pyqtSlot()
def on_accepted(self):
# print "emit: ", self.message_input.text()
self.got_message.emit(self.message_input.text())
self.input_finished.wakeAll()
class MyThread(QtCore.QThread):
mutex = QtCore.QMutex()
load_message_input = QtCore.pyqtSignal()
def __init__(self, id, window):
super(MyThread, self).__init__()
self.id = id
self.window = window
# self.mutex = QtCore.QMutex()
def run(self):
print "Thread %d is started" % self.id
MyThread.mutex.lock()
self.get_captcha_value()
print "Thread %d is finishing" % self.id
def get_captcha_value(self):
print "Thread %d locks mutex" % self.id
self.load_message_input.connect(self.window.show_input, QtCore.Qt.BlockingQueuedConnection)
self.load_message_input.emit()
self.window.got_message.connect(self.print_message)
self.window.input_finished.wait(MyThread.mutex)
print "Thread %d unlocks mutex" % self.id
MyThread.mutex.unlock()
@QtCore.pyqtSlot("QString")
def print_message(self, msg):
print "Thread %d: %s" % (self.id, msg)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
window = test_qdialog.MyDialog()
threads = []
for i in range(5):
thread = MyThread(i, window)
if not thread.isRunning():
thread.start()
threads.append(thread)
sys.exit(app.exec_())
При запуске в консоли получается так:
Thread 0 is startedThread 2 is started
Thread 0 locks mutex
Thread 3 is startedThread 1 is started
Thread 4 is started
showing input
Thread 2 locks mutex
showing input
Thread 3 locks mutex
showing input
Thread 4 locks mutex
showing input
Thread 1 locks mutex
showing input
Thread 0: hello
Thread 2: hello
Thread 3: hello
Thread 4: hello
Thread 1: hello
Thread 0 unlocks mutex
Thread 0 is finishing
Thread 4 unlocks mutex
Thread 4 is finishingThread 3 unlocks mutex
Thread 3 is finishingThread 2 unlocks mutex
Thread 2 is finishing
Thread 1 unlocks mutex
Thread 1 is finishing