1

ロボットを制御するコントローラー クラスがあります (シリアル インターフェイス経由で接続)。このコントローラーはビューにアタッチされています。それに加えて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 メソッドをトリガーした後、ユーザー インターフェイスがフリーズし、プログラムがクラッシュします。なぜですか? どうすればそれを回避できますか?

4

1 に答える 1

3

コードサンプルが不完全であるためわかりにくいですが、このコードには2つの根本的な問題があります。

  1. 2つの異なる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

于 2012-08-04T22:19:06.760 に答える