python - QMutexLocker() 导致 UI 卡住

标签 python multithreading pyqt mutex robot

我有一个控制机器人的 Controller 类(通过串行接口(interface)连接)。该 Controller 附加到 View 。除此之外,我还有一个从 QThread 派生的线程,它定期读取机器人的状态。

读取状态不得与从用户界面触发的机器人命令相冲突。因此,我使用 QMutexLocker 使用互斥体锁定了每个机器人访问,但是如果执行这样的互斥体 block ,这会导致我的用户界面卡住。

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 方法后,用户界面卡住并且程序崩溃:为什么会这样?我怎样才能避免这种情况?

最佳答案

很难说,因为您的代码示例不完整,但我发现此代码存在两个基本问题:

  1. 您正在锁定两个不同的 QMutex 对象。为了使互斥正常工作,两个线程必须锁定同一个互斥对象。

  2. 您似乎在这一行的更新线程中直接与 GUI 交互:

    self.view.robotcontrolui.update_position_and_status(rel_pos, status)
    

    执行 GUI 操作可能只能从 Qt 中的 GUI 线程完成。可以肯定这是导致您崩溃的原因。请参阅:http://qt-project.org/doc/qt-4.8/threads.html

关于python - QMutexLocker() 导致 UI 卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11810812/

相关文章:

python - 测试 pyqt 应用程序 - Qwidget : must construct a qapplication before a qwidget

python - 更改记录器在 python 中生成的默认位置日志文件

python - 使用 Python 将整数转换为两个字节的十六进制

c# - 任务继续被安排到非线程池线程。为什么?

postgresql - 在 PyQt5 中使用 PostgreSQL 的正确方法是什么

python - PyQt:具有撤消和重做操作的 QTableWidget

python - 标签颜色更改其他标签

c++ - C/C++ 与 Python 之间交换值的应用程序设计

c# - 如何立即杀死C#中的Thread

c++ - 如何在两个线程之间共享公共(public)资源?