Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. How to Use Multithreading
Forum Updated to NodeBB v4.3 + New Features

How to Use Multithreading

Scheduled Pinned Locked Moved Solved Qt for Python
15 Posts 3 Posters 2.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J.HilkJ J.Hilk

    @vidyul let me chatgpt that for you:

    To continuously fetch data and update the display in real-time, you can use a separate thread to fetch the data and emit a signal every time new data is available. The main thread can then connect a slot to this signal to update the UI. Here’s a simplified example:

    class DataThread(QThread):
        data_signal = pyqtSignal(object)
    
        def run(self):
            while True:
                data = self.fetch_data()  # replace with your data fetching logic
                self.data_signal.emit(data)
                time.sleep(1)  # sleep for a while to prevent high CPU usage
    
    class ATE_UI(QDialog):
        def __init__(self):
            super(ATE_UI,self).__init__()
            loadUi('ATE_Update.ui',self)
            
            self.Reports_Table.setColumnWidth(0,250)
            
            self.label_4.setText('Flight Mode: VTOL')
            
            timer=QTimer(self)
            timer.timeout.connect(self.showTime)
            timer.start(1)
            self.Test_Button.clicked.connect(self.start_fetching_data)
            self.Save_Button.clicked.connect(self.save_data)
    
            self.data_thread = DataThread()
            self.data_thread.data_signal.connect(self.update_display)
    
        def start_fetching_data(self):
            self.data_thread.start()
    
        def update_display(self, data):
            # update your display with the new data here
            pass
    
        # ... rest of your code ...
    
    

    In this example, pressing the Test_Button will start the DataThread, which fetches data in a loop until stopped. Every time new data is fetched, it emits a signal with the data, which is connected to the update_display slot in the main thread. This slot can then update the UI with the new data.

    Please replace self.fetch_data() with your actual data fetching logic and implement the update_display method to update your UI with the new data. Also, don’t forget to handle stopping the thread when necessary. You might want to add a stop button and connect it to a method that calls self.data_thread.terminate(). Be aware that terminating threads can be dangerous if not handled properly, so it’s better to have a mechanism in your thread to stop it gracefully. For example, you can use a QMutex and a flag to check whether the thread should stop or continue fetching data. If the flag is set, the thread can finish its current iteration and then stop itself by returning from the run method. This way, you can avoid abruptly stopping the thread and potentially leaving resources in an inconsistent state.

    Please note that this is a simplified example and might not cover all edge cases. Always make sure to handle exceptions and edge cases in your code to prevent crashes and ensure a smooth user experience. Also, keep in mind that updating the UI from a different thread is not safe, and you should always use signals and slots for communication between threads in Qt.

    V Offline
    V Offline
    vidyul
    wrote on last edited by
    #6

    @J-Hilk thank you for the help. I have run a sample code and it is running, I will update here as solved when everything works fine.

    1 Reply Last reply
    1
    • V vidyul has marked this topic as solved on
    • J.HilkJ J.Hilk

      @vidyul let me chatgpt that for you:

      To continuously fetch data and update the display in real-time, you can use a separate thread to fetch the data and emit a signal every time new data is available. The main thread can then connect a slot to this signal to update the UI. Here’s a simplified example:

      class DataThread(QThread):
          data_signal = pyqtSignal(object)
      
          def run(self):
              while True:
                  data = self.fetch_data()  # replace with your data fetching logic
                  self.data_signal.emit(data)
                  time.sleep(1)  # sleep for a while to prevent high CPU usage
      
      class ATE_UI(QDialog):
          def __init__(self):
              super(ATE_UI,self).__init__()
              loadUi('ATE_Update.ui',self)
              
              self.Reports_Table.setColumnWidth(0,250)
              
              self.label_4.setText('Flight Mode: VTOL')
              
              timer=QTimer(self)
              timer.timeout.connect(self.showTime)
              timer.start(1)
              self.Test_Button.clicked.connect(self.start_fetching_data)
              self.Save_Button.clicked.connect(self.save_data)
      
              self.data_thread = DataThread()
              self.data_thread.data_signal.connect(self.update_display)
      
          def start_fetching_data(self):
              self.data_thread.start()
      
          def update_display(self, data):
              # update your display with the new data here
              pass
      
          # ... rest of your code ...
      
      

      In this example, pressing the Test_Button will start the DataThread, which fetches data in a loop until stopped. Every time new data is fetched, it emits a signal with the data, which is connected to the update_display slot in the main thread. This slot can then update the UI with the new data.

      Please replace self.fetch_data() with your actual data fetching logic and implement the update_display method to update your UI with the new data. Also, don’t forget to handle stopping the thread when necessary. You might want to add a stop button and connect it to a method that calls self.data_thread.terminate(). Be aware that terminating threads can be dangerous if not handled properly, so it’s better to have a mechanism in your thread to stop it gracefully. For example, you can use a QMutex and a flag to check whether the thread should stop or continue fetching data. If the flag is set, the thread can finish its current iteration and then stop itself by returning from the run method. This way, you can avoid abruptly stopping the thread and potentially leaving resources in an inconsistent state.

      Please note that this is a simplified example and might not cover all edge cases. Always make sure to handle exceptions and edge cases in your code to prevent crashes and ensure a smooth user experience. Also, keep in mind that updating the UI from a different thread is not safe, and you should always use signals and slots for communication between threads in Qt.

      V Offline
      V Offline
      vidyul
      wrote on last edited by
      #7

      @J-Hilk I have marked it as correct answer. I just wanted to know it for my knowledge that Can I have more than 1 worker class inherited from Q Thread? And How can I achieve that? It can be useful for me in the future.

      jsulmJ 1 Reply Last reply
      0
      • V vidyul

        @J-Hilk I have marked it as correct answer. I just wanted to know it for my knowledge that Can I have more than 1 worker class inherited from Q Thread? And How can I achieve that? It can be useful for me in the future.

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #8

        @vidyul said in How to Use Multithreading:

        Can I have more than 1 worker class inherited from Q Thread?

        Sure, each of the worker runs then in its own thread.
        "And How can I achieve that?" - in the same way you create one worker.

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        V 1 Reply Last reply
        1
        • jsulmJ jsulm

          @vidyul said in How to Use Multithreading:

          Can I have more than 1 worker class inherited from Q Thread?

          Sure, each of the worker runs then in its own thread.
          "And How can I achieve that?" - in the same way you create one worker.

          V Offline
          V Offline
          vidyul
          wrote on last edited by vidyul
          #9

          @jsulm
          @J-Hilk
          Thank you for that info. I am currently facing an issue with the QThread you suggested.
          After I finish with my task I am clicking a button and then going back to login page, but in the background the qthread is still running and printing the output. How should I end that thread when pressed the stop button and again use it when I press the button to start the process.

          J.HilkJ 1 Reply Last reply
          0
          • V vidyul

            @jsulm
            @J-Hilk
            Thank you for that info. I am currently facing an issue with the QThread you suggested.
            After I finish with my task I am clicking a button and then going back to login page, but in the background the qthread is still running and printing the output. How should I end that thread when pressed the stop button and again use it when I press the button to start the process.

            J.HilkJ Online
            J.HilkJ Online
            J.Hilk
            Moderators
            wrote on last edited by
            #10

            @vidyul usually you call quit() on the thread. Doesn't necessarily work, depends on what you're doing inside the thread. If there's no event loop running, but something like an infinite while loop. You'll have to quit that first.


            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            V 1 Reply Last reply
            0
            • J.HilkJ J.Hilk

              @vidyul usually you call quit() on the thread. Doesn't necessarily work, depends on what you're doing inside the thread. If there's no event loop running, but something like an infinite while loop. You'll have to quit that first.

              V Offline
              V Offline
              vidyul
              wrote on last edited by
              #11

              @J-Hilk Yes, so in the def run there is a while True running. Will I have to pass the button(s) as an object when I am creating an instance of the DataThread class?

              Or I need to do something else?

              J.HilkJ 1 Reply Last reply
              0
              • V vidyul

                @J-Hilk Yes, so in the def run there is a while True running. Will I have to pass the button(s) as an object when I am creating an instance of the DataThread class?

                Or I need to do something else?

                J.HilkJ Online
                J.HilkJ Online
                J.Hilk
                Moderators
                wrote on last edited by
                #12

                @vidyul I'm not an expert in Python, but I assume there are equivalents to Atomics and or mutex? You need to check that variable every so often inside the loop and exit the loop when the condition is set.

                Let me ask the AI to whip up an example.


                Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                Q: What's that?
                A: It's blue light.
                Q: What does it do?
                A: It turns blue.

                J.HilkJ V 2 Replies Last reply
                0
                • J.HilkJ J.Hilk

                  @vidyul I'm not an expert in Python, but I assume there are equivalents to Atomics and or mutex? You need to check that variable every so often inside the loop and exit the loop when the condition is set.

                  Let me ask the AI to whip up an example.

                  J.HilkJ Online
                  J.HilkJ Online
                  J.Hilk
                  Moderators
                  wrote on last edited by
                  #13

                  @J-Hilk here you go:

                  import sys
                  import time
                  from PyQt5.QtCore import Qt, QThread, QTimer, QObject, QMutex, pyqtSignal
                  from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget
                  
                  class Worker(QObject):
                      finished = pyqtSignal()
                  
                      def __init__(self, mutex):
                          super().__init__()
                          self.mutex = mutex
                          self.stop_flag = False
                  
                      def run_long_task(self):
                          while not self.stop_flag:
                              # Simulate some work
                              time.sleep(1)
                              print("Worker thread: Doing some work...")
                  
                          self.finished.emit()
                  
                  class Window(QMainWindow):
                      def __init__(self):
                          super().__init__()
                          self.clicksCount = 0
                          self.setup_ui()
                  
                      def setup_ui(self):
                          self.setWindowTitle("Thread Example")
                          self.resize(300, 150)
                          self.centralWidget = QWidget()
                          self.setCentralWidget(self.centralWidget)
                  
                          # Create widgets
                          self.clicksLabel = QLabel("Counting: 0 clicks", self)
                          self.clicksLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                          self.countBtn = QPushButton("Click me!", self)
                          self.countBtn.clicked.connect(self.count_clicks)
                          self.longRunningBtn = QPushButton("Long-Running Task!", self)
                          self.longRunningBtn.clicked.connect(self.run_long_task)
                  
                          # Set layout
                          layout = QVBoxLayout()
                          layout.addWidget(self.clicksLabel)
                          layout.addWidget(self.countBtn)
                          layout.addStretch()
                          layout.addWidget(self.longRunningBtn)
                          self.centralWidget.setLayout(layout)
                  
                      def count_clicks(self):
                          self.clicksCount += 1
                          self.clicksLabel.setText(f"Counting: {self.clicksCount} clicks")
                  
                      def run_long_task(self):
                          mutex = QMutex()
                          worker = Worker(mutex)
                  
                          def stop_worker():
                              with mutex:
                                  worker.stop_flag = True
                  
                          # Connect the worker's finished signal to stop the worker
                          worker.finished.connect(stop_worker)
                  
                          # Start the worker thread
                          thread = QThread()
                          worker.moveToThread(thread)
                          thread.started.connect(worker.run_long_task)
                          thread.start()
                  
                  if __name__ == "__main__":
                      app = QApplication(sys.argv)
                      win = Window()
                      win.show()
                      sys.exit(app.exec_())
                  
                  

                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  V 1 Reply Last reply
                  0
                  • J.HilkJ J.Hilk

                    @vidyul I'm not an expert in Python, but I assume there are equivalents to Atomics and or mutex? You need to check that variable every so often inside the loop and exit the loop when the condition is set.

                    Let me ask the AI to whip up an example.

                    V Offline
                    V Offline
                    vidyul
                    wrote on last edited by
                    #14
                    This post is deleted!
                    1 Reply Last reply
                    0
                    • J.HilkJ J.Hilk

                      @J-Hilk here you go:

                      import sys
                      import time
                      from PyQt5.QtCore import Qt, QThread, QTimer, QObject, QMutex, pyqtSignal
                      from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget
                      
                      class Worker(QObject):
                          finished = pyqtSignal()
                      
                          def __init__(self, mutex):
                              super().__init__()
                              self.mutex = mutex
                              self.stop_flag = False
                      
                          def run_long_task(self):
                              while not self.stop_flag:
                                  # Simulate some work
                                  time.sleep(1)
                                  print("Worker thread: Doing some work...")
                      
                              self.finished.emit()
                      
                      class Window(QMainWindow):
                          def __init__(self):
                              super().__init__()
                              self.clicksCount = 0
                              self.setup_ui()
                      
                          def setup_ui(self):
                              self.setWindowTitle("Thread Example")
                              self.resize(300, 150)
                              self.centralWidget = QWidget()
                              self.setCentralWidget(self.centralWidget)
                      
                              # Create widgets
                              self.clicksLabel = QLabel("Counting: 0 clicks", self)
                              self.clicksLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                              self.countBtn = QPushButton("Click me!", self)
                              self.countBtn.clicked.connect(self.count_clicks)
                              self.longRunningBtn = QPushButton("Long-Running Task!", self)
                              self.longRunningBtn.clicked.connect(self.run_long_task)
                      
                              # Set layout
                              layout = QVBoxLayout()
                              layout.addWidget(self.clicksLabel)
                              layout.addWidget(self.countBtn)
                              layout.addStretch()
                              layout.addWidget(self.longRunningBtn)
                              self.centralWidget.setLayout(layout)
                      
                          def count_clicks(self):
                              self.clicksCount += 1
                              self.clicksLabel.setText(f"Counting: {self.clicksCount} clicks")
                      
                          def run_long_task(self):
                              mutex = QMutex()
                              worker = Worker(mutex)
                      
                              def stop_worker():
                                  with mutex:
                                      worker.stop_flag = True
                      
                              # Connect the worker's finished signal to stop the worker
                              worker.finished.connect(stop_worker)
                      
                              # Start the worker thread
                              thread = QThread()
                              worker.moveToThread(thread)
                              thread.started.connect(worker.run_long_task)
                              thread.start()
                      
                      if __name__ == "__main__":
                          app = QApplication(sys.argv)
                          win = Window()
                          win.show()
                          sys.exit(app.exec_())
                      
                      
                      V Offline
                      V Offline
                      vidyul
                      wrote on last edited by vidyul
                      #15

                      @J-Hilk
                      So the current main.py file is:
                      sample.png
                      Now I want to know where should I implement this part:
                      def run_long_task(self):
                      mutex = QMutex()
                      worker = Worker(mutex)

                          def stop_worker():
                              with mutex:
                                  worker.stop_flag = True
                      
                          # Connect the worker's finished signal to stop the worker
                          worker.finished.connect(stop_worker)
                      

                      because I tried but it was not working. It prompt to force close the UI.
                      @J-Hilk

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved