gpt4 book ai didi

python - PyQt4:如何避免这种竞争条件? QThread 在完全启动之前断开连接

转载 作者:太空宇宙 更新时间:2023-11-04 06:33:03 24 4
gpt4 key购买 nike

我有一种情况,我想使用单个 QThread 在不同时间运行两个(或更多)单独的方法。例如,有时我希望 QThread 运行 play(),当我完成播放时,我想断开 QThread 与此方法的连接,以便我可以将它连接到其他地方。本质上,我希望 QThread 充当任何我想与主进程并行运行的容器。

我遇到了启动 QThread 然后立即断开连接导致运行时出现奇怪行为的问题。在我发现“竞争条件”是什么意思(或者真正了解多线程)之前,我暗暗怀疑线程在断开连接之前没有完全启动。为了克服这个问题,我在 start()disconnect() 调用之间添加了 5 毫秒的 sleep 时间,效果非常好。它就像一个魅力,但它不是正确的方法。

如何在不调用 sleep() 的情况下使用一个 QThread 实现此功能?

问题中的代码片段:

def play(self):

self.stateLabel.setText("Status: Playback initated ...")

self.myThread.started.connect(self.mouseRecorder.play)
self.myThread.start()
time.sleep(.005) #This is the line I'd like to eliminate

self.myThread.started.disconnect()

完整脚本:

class MouseRecord(QtCore.QObject):

finished = QtCore.pyqtSignal()

def __init__(self):

super(MouseRecord, self).__init__()

self.isRecording = False
self.cursorPath = []

@QtCore.pyqtSlot()
def record(self):

self.isRecording = True
self.cursorPath = []

while(self.isRecording):

self.cursorPath.append(win32api.GetCursorPos())
time.sleep(.02)

self.finished.emit()

def stop(self):

self.isRecording = False

@QtCore.pyqtSlot()
def play(self):

for pos in self.cursorPath:
win32api.SetCursorPos(pos)
time.sleep(.02)

print "Playback complete!"
self.finished.emit()

class CursorCapture(QtGui.QWidget):

def __init__(self):

super(CursorCapture, self).__init__()

self.mouseRecorder = MouseRecord()

self.myThread = QtCore.QThread()

self.mouseRecorder.moveToThread(self.myThread)
self.mouseRecorder.finished.connect(self.myThread.quit)

self.initUI()

def initUI(self):

self.recordBtn = QtGui.QPushButton("Record")
self.stopBtn = QtGui.QPushButton("Stop")
self.playBtn = QtGui.QPushButton("Play")

self.recordBtn.clicked.connect(self.record)
self.stopBtn.clicked.connect(self.stop)
self.playBtn.clicked.connect(self.play)

self.stateLabel = QtGui.QLabel("Status: Stopped.")

#Bunch of other GUI initialization ...

def record(self):

self.stateLabel.setText("Status: Recording ...")

self.myThread.started.connect(self.mouseRecorder.record)
self.myThread.start()
time.sleep(.005)

self.myThread.started.disconnect()

def play(self):

self.stateLabel.setText("Status: Playback initated ...")

self.myThread.started.connect(self.mouseRecorder.play)
self.myThread.start()
time.sleep(.005)

self.myThread.started.disconnect()

最佳答案

正确的方法是为每个 Action 创建新的QThread,这样就不需要 sleep 和断开连接了。现在,即使您成功消除了 sleep 调用,也可能出现以下情况:

1) 您运行play,然后断开插槽

2) 在play 完成之前运行record。在这种情况下,先前创建的线程仍在运行,并且:

If the thread is already running, this function does nothing.

(来自documentation)

但是,如果您接受这种情况并以某种方式防止同时“播放”和“录制”,那么您应该按照您自己写的那样做:“当我玩完后,我想断开连接”。所以,不仅仅是在线程启动之后,而是在它完成之后。要做到这一点试试这个:

1) 将self.mouseRecorder.finished.connect(self.myThread.quit)更改为self.mouseRecorder.finished.connect(self.threadFinished)

2) 实现:

def threadFinished(self):
self.myThread.quit()
self.myThread.started.disconnect()

关于python - PyQt4:如何避免这种竞争条件? QThread 在完全启动之前断开连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14699412/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com