Reputation: 8211
I have a controller class which controls a robot (attached over serial interface). This controller is attached to a view. In addition to that I have a thread derived from QThread
which periodically reads out the status of the robot.
Reading out the status must not colide with robot commands which get tiggered from the userinterface. Therefore I locked every robot acces with a mutex using QMutexLocker
but this causes my userinterface to freeze if such a mutex block gets executed.
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!"))
After triggering the init method the userinterface freezes and the program crashes: Why is this so? How can I avoid that?
Upvotes: 1
Views: 1607
Reputation: 11644
It's hard to tell because your code sample is incomplete, but I see two fundamental problems with this code:
You are locking two different QMutex objects. In order for mutual exclusion to work properly, both threads must be locking the same mutex object.
You appear to be directly interacting with the GUI from the update thread at this line:
self.view.robotcontrolui.update_position_and_status(rel_pos, status)
Performing GUI operations may only be done from the GUI thread in Qt. It's a fair bet that this is causing your crash. See: http://qt-project.org/doc/qt-4.8/threads.html
Upvotes: 3