我有一个控制器类来控制机器人(通过串行接口连接)。该控制器附加到视图。除此之外,我还有一个派生自QThread
的线程,它定期读出机器人的状态。
读出状态不得与机器人命令一致,这些命令会从用户界面中触发。因此,我使用QMutexLocker
使用互斥锁锁定每个机器人访问,但是如果执行了这样的互斥块,这会导致我的用户界面冻结。
class RobotControl(QObject):
def __init__(self, view):
super(RobotControl, self).__init__()
self.view = view
self.updatethread = UpdatePositionAndStatus(self.robot)
self.mutex = QMutex()
self.connect(self.updatethread, SIGNAL("updateStatus( QString ) "), self.print_error)
self.updatethread.start()
@pyqtSlot()
def init_robot(self):
"""
Initializes the serial interface to the robot interface and checks if
there is really a robot interface available.
"""
with QMutexLocker(self.mutex):
# Open interface
try:
index = self.view.robotcontrolui.get_selected_interface_index()
interface = self.interfaces.item(index).text()
self.robot = RobotController(interface)
except DeviceError:
self.view.error_dlg(self.tr("Couldn't open interface {0}!".format(interface)))
self.robot = None
return
# Check if there is really a robot interface on the selected serial
# interface with trying to read status byte
try:
self.robot.status()
except DeviceError:
# In case of failure release interface
self.close_robot()
self.view.error_dlg(self.tr("Couldn't initialize robot interface!"))
return
self.view.robotcontrolui.bt_open_interface.setEnabled(False)
self.view.robotcontrolui.bt_close_interface.setEnabled(True)
class UpdatePositionAndStatus(QThread):
def __init__(self, robot, parent=None):
QThread.__init__(self, parent)
self.robot = robot
self.mutex = QMutex()
def run(self):
"""
This function continously reads out the position and the status to for
updating it on the userinterface.
"""
try:
while True:
if self.robot is not None:
# Do robot communication under a lock
self.mutex.lock()
(_, rel_pos) = self.robot.read_position()
status = self.robot.status()
self.mutex.unlock()
# Display position and status on userinterface
self.view.robotcontrolui.update_position_and_status(rel_pos, status)
# Wait 1 seccond for next update
QThread.sleep(1.0)
except DeviceError:
# Release lock on robot
self.mutex.unlock()
self.emit(SIGNAL("updateStatus( QString )"), self.tr("Error while updating current position and status!"))
触发init方法后,用户界面冻结,程序崩溃:为什么会这样?我怎么能避免这种情况?
答案 0 :(得分:3)
很难分辨,因为您的代码示例不完整,但我发现此代码有两个基本问题:
您正在锁定两个不同的QMutex对象。为了使互斥能够正常工作,两个线程必须锁定相同的互斥对象。
您似乎直接在此行的更新线程中与GUI进行交互:
self.view.robotcontrolui.update_position_and_status(rel_pos, status)
执行GUI操作只能从Qt中的GUI线程完成。这是一个公平的赌注,这是导致你的崩溃。请参阅:http://qt-project.org/doc/qt-4.8/threads.html