Uploaded image for project: 'Qt for Python'
  1. Qt for Python
  2. PYSIDE-2990

Slot Executed in Signal's Thread Even With Auto & QueuedConnection

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Invalid
    • Icon: Not Evaluated Not Evaluated
    • None
    • 6.8
    • PySide
    • None
    • macOS, Windows

      It's first reported here.

       The slot is always executed in the signal caller's thread, even with explicit QueuedConnection, when a worker approach is used. The following minimal example is almost identical to the example from the official document.

      import sys
      
      from PySide6.QtCore import QObject, Signal, QThread, Qt, Slot
      from PySide6.QtWidgets import QMainWindow, QApplication
      
      
      class Worker(QObject):
          update = Signal()
      
          def run(self):
              print(f"worker: {QThread.currentThread().objectName()}")
              self.update.emit()
      
      
      class Window(QMainWindow):
          def __init__(self, parent=None):
              super().__init__(parent)
              worker = Worker()
              thread = QThread(self)
              thread.setObjectName('test thread')
              worker.moveToThread(thread)
              thread.started.connect(worker.run)
              worker.update.connect(self.update)
              thread.start()
      
          @Slot()
          def update(self):
              print(f"window: {QThread.currentThread().objectName()}")
      
      
      if __name__ == '__main__':
          app = QApplication()
          w = Window()
          w.show()
          sys.exit(app.exec())
      

      The output is

      worker: Qt mainThread
      window: test thread
      

      However, the problem doesn't exist when switched to subclassing QThread:

      import sys
      
      from PySide6.QtCore import QObject, Signal, QThread, Qt, Slot
      from PySide6.QtWidgets import QMainWindow, QApplication
      
      
      class Thread(QThread):
          update = Signal()
      
          def run(self):
              print(f"thread: {QThread.currentThread().objectName()}")
              self.update.emit()
      
      
      class Window(QMainWindow):
          def __init__(self, parent=None):
              super().__init__(parent)
              thread = Thread(self)
              thread.setObjectName('test thread')
              thread.update.connect(self.update)
              thread.start()
      
          @Slot()
          def update(self):
              print(f"window: {QThread.currentThread().objectName()}")
      
      
      if __name__ == '__main__':
          app = QApplication()
          w = Window()
          w.show()
          sys.exit(app.exec())
      

      I tried the cpp equivalent version and it works fine. Source code is attached in the zip file. Result of cpp version:

      2025-01-21 18:19:49.155575-0500 qt_test[86901:106814649] Worker::process  "test thread"
      2025-01-21 18:19:50.033013-0500 qt_test[86901:106814599] Window::process  "Qt mainThread"
      

        1. cpp-test.zip
          3 kB
          Xun Yuan
        2. pyside2990.py
          1 kB
          Friedemann Kleint
        3. pyside2990_fixed.py
          1 kB
          Friedemann Kleint
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            crmaurei Cristian Maureira-Fredes
            yuanxun Xun Yuan
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:

                There are no open Gerrit changes