Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. passing a parameter to a method causes Window to freeze
Forum Updated to NodeBB v4.3 + New Features

passing a parameter to a method causes Window to freeze

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 4 Posters 758 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.
  • R Offline
    R Offline
    robliou
    wrote on last edited by robliou
    #1

    Hi! I've been able to (mostly) successfully use pyqt5 to create a benchmarking app that runs a series of algorithms/tests based on the number of trials desired by the user. I have set up 5 different tests that are all variations of the same formula. For example, in the first test, the algorithm is run 10 times, while in the second test, it is run 20 times, etc.

    What I find confounding is that if I use DRY principles to simplify this test into a single function with a parameter passed to the function to indicate the number of trials to be run (i.e. n=10, n=20, etc), it causes the pyqt5 app (Window) to freeze/ hang when the function is called. For example, using the following syntax to call my method will result in a freeze.

    result = runTest_A(num_shots)
    

    Whereas, if I create 5 separate methods and then hardcode the number of trials (10,20,30, etc) into each method such that no variable is needed to be passed, and then run them, then the app works fine and does not hang while the methods are running (i.e.)

    result = runTest_A_no_parameter()
    

    It should be noted that in either case, the underlying methods run just fine in the background. The issue is that the GUI freezes in the first case when a variable is passed. It should be further noted that I am using threads to run the functions when they are called, i.e.:

            # Start running functions in a separate thread
            self.thread = QThread()
            self.worker.moveToThread(self.thread)   self.thread.started.connect(self.worker.run_function_A)
    
            self.thread.start()
    

    Does anyone have any experience with this issue, or know how to solve it? Is using Queue or something similar something I should consider? Is this issue fixed in pyqt6?

    Thanks in advance,

    A2.png
    Case 1:Window does not hang when functions called do not have passed parameters

    A1.png
    Case 2: Window hangs/ freezes when functions called do have passed parameters

    JonBJ 1 Reply Last reply
    0
    • R robliou

      Hi! I've been able to (mostly) successfully use pyqt5 to create a benchmarking app that runs a series of algorithms/tests based on the number of trials desired by the user. I have set up 5 different tests that are all variations of the same formula. For example, in the first test, the algorithm is run 10 times, while in the second test, it is run 20 times, etc.

      What I find confounding is that if I use DRY principles to simplify this test into a single function with a parameter passed to the function to indicate the number of trials to be run (i.e. n=10, n=20, etc), it causes the pyqt5 app (Window) to freeze/ hang when the function is called. For example, using the following syntax to call my method will result in a freeze.

      result = runTest_A(num_shots)
      

      Whereas, if I create 5 separate methods and then hardcode the number of trials (10,20,30, etc) into each method such that no variable is needed to be passed, and then run them, then the app works fine and does not hang while the methods are running (i.e.)

      result = runTest_A_no_parameter()
      

      It should be noted that in either case, the underlying methods run just fine in the background. The issue is that the GUI freezes in the first case when a variable is passed. It should be further noted that I am using threads to run the functions when they are called, i.e.:

              # Start running functions in a separate thread
              self.thread = QThread()
              self.worker.moveToThread(self.thread)   self.thread.started.connect(self.worker.run_function_A)
      
              self.thread.start()
      

      Does anyone have any experience with this issue, or know how to solve it? Is using Queue or something similar something I should consider? Is this issue fixed in pyqt6?

      Thanks in advance,

      A2.png
      Case 1:Window does not hang when functions called do not have passed parameters

      A1.png
      Case 2: Window hangs/ freezes when functions called do have passed parameters

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @robliou
      Passing parameters or not should not be relevant. Blocking the event loop might cause a "freeze", and if you do anything UI from your threads that would be undefined. Threads are often a cause of problems. Please produce a minimal example of whatever you are doing which shows the issue, and a corresponding one which does not.

      R 2 Replies Last reply
      0
      • JonBJ JonB

        @robliou
        Passing parameters or not should not be relevant. Blocking the event loop might cause a "freeze", and if you do anything UI from your threads that would be undefined. Threads are often a cause of problems. Please produce a minimal example of whatever you are doing which shows the issue, and a corresponding one which does not.

        R Offline
        R Offline
        robliou
        wrote on last edited by robliou
        #3

        @JonB

        Sure thing. Assume I have a method called 'run_all_tests' which runs 5 sub- tests:

        def run_all_tests(num_shots):
           result_a = runTest_A(num_shots)
           result_b = runTest_B(num_shots)
           result_c = runTest_C(num_shots)
           result_d = runTest_D(num_shots)
           result_e = runTest_E(num_shots)
        

        if I call run_all_tests(100), then run_all_tests() will correctly pass the parameter 100 to each subtest and they all run fine in the background. However, in my qt Window widget it will hang (i.e I click anywhere on the window while it is running). Whereas, if I edit runTest_A, runTest_B, etc. such that the number of shots is hardcoded, and as such no parameter needs to be passed, as follows:

        def run_all_tests():
           result_a = runTest_A()
           result_b = runTest_B()
           result_c = runTest_C()
           result_d = runTest_D()
           result_e = runTest_E()
        

        and then call run_all_tests(), then all 5 sub- functions again run properly in order, but with no qt Window hanging issues, even if I click somewhere on the Window itself.

        The way my run_all_tests() function is connected is as follows (note that the function launches on the event of a button click):

        ...
        elif selected_item == 'Multi-test':
              self.thread = QThread()
              self.worker.moveToThread(self.thread)                  
              self.thread.started.connect(self.run_all_tests)
              self.thread.start()            
        

        I'm open to any suggestions you may have, thank you.

        R S 2 Replies Last reply
        0
        • R robliou

          @JonB

          Sure thing. Assume I have a method called 'run_all_tests' which runs 5 sub- tests:

          def run_all_tests(num_shots):
             result_a = runTest_A(num_shots)
             result_b = runTest_B(num_shots)
             result_c = runTest_C(num_shots)
             result_d = runTest_D(num_shots)
             result_e = runTest_E(num_shots)
          

          if I call run_all_tests(100), then run_all_tests() will correctly pass the parameter 100 to each subtest and they all run fine in the background. However, in my qt Window widget it will hang (i.e I click anywhere on the window while it is running). Whereas, if I edit runTest_A, runTest_B, etc. such that the number of shots is hardcoded, and as such no parameter needs to be passed, as follows:

          def run_all_tests():
             result_a = runTest_A()
             result_b = runTest_B()
             result_c = runTest_C()
             result_d = runTest_D()
             result_e = runTest_E()
          

          and then call run_all_tests(), then all 5 sub- functions again run properly in order, but with no qt Window hanging issues, even if I click somewhere on the Window itself.

          The way my run_all_tests() function is connected is as follows (note that the function launches on the event of a button click):

          ...
          elif selected_item == 'Multi-test':
                self.thread = QThread()
                self.worker.moveToThread(self.thread)                  
                self.thread.started.connect(self.run_all_tests)
                self.thread.start()            
          

          I'm open to any suggestions you may have, thank you.

          R Offline
          R Offline
          robliou
          wrote on last edited by
          #4

          @JonB
          Checking out my code again, it's possible the issue has less to do with passing parameters to methods and more to do with the fact that I'm offloading a method to other files and then trying to run it from main.py?

          After all, my original main.py file has grown to be quite large; it has two classes, Worker() and Main(), with each one having multiple methods. For simplicity's sake, I tried to move some of the methods to other files and then import them into my main.py file. The importing works fine, but it causes the hanging issue with qt Window.

          For example, I have a run_multi() method that I offloaded into a separate run_multi.py file and then re-imported into my main.py via:

          from functions.run_multi import run_multi_main
          
          class Worker(QObject):
          
              def main(self):
                     run_multi_imported = run_multi_main(self)
                     return run_multi_imported
          

          and then called later on, after button press, in my Main() class in the same file via:

          elif selected_item == 'Multi-test':
                      self.thread = QThread()
                      self.worker.moveToThread(self.thread)
                      self.thread.started.connect(lambda: self.worker.main())
                      self.thread.start()
          

          Again, if I never offloaded this run_multi() function into a separate file and kept it in main.py, then everything runs smoothly in qt with no hanging issues. But I noticed when I imported it, the qt hanging issues arose. Any thoughts?

          Thanks,

          1 Reply Last reply
          0
          • JonBJ JonB

            @robliou
            Passing parameters or not should not be relevant. Blocking the event loop might cause a "freeze", and if you do anything UI from your threads that would be undefined. Threads are often a cause of problems. Please produce a minimal example of whatever you are doing which shows the issue, and a corresponding one which does not.

            R Offline
            R Offline
            robliou
            wrote on last edited by robliou
            #5

            @JonB
            This is probably the cleanest way for me to explain the issue: seen below, I have a method called 'run_all_functions' in my Worker() class which allows the user to select which suite of algos to run based on the click of a button (attached to a dropdown menu within qt):

            import suite_1_algo_a, suite_1_algo_b, suite_1_algo_c
            import suite_2_algo_a, suite_2_algo_b, suite_2_algo_c
            
                class Worker(QObject):
            
                    def run_all_functions(self):
                        if algo == 'suite_1':            
                                test_a = suite_1_algo_a
                                test_b = suite_1_algo_b
                                test_c = suite_1_algo_c
                        if algo == 'suite_2':            
                                test_a = suite_2_algo_a
                                test_b = suite_2_algo_b
                                test_c = suite_2_algo_c
            
                        result_1 = test_a.main
                        result_2 = test_b.main
                        result_3 = test_c.main
                  
                        print('result_1:', result_1 )
                        print('result_2:', result_2 )
                        print('result_3:', result_3)
            

            After selecting which suite to run, the pyqt Window will hang even as the selected function is running in the background. Whereas, if I simply create two separate functions with the values for test_a, test_b, and test_c hardcoded (i.e. no if/else option at the start for various algo scenarios), and then run either hardcoded function based on the press of a qt button, then the Window widget does not hang. Both the hardcoded and non-hardcoded functions are similarly initiated as threads, as follows:

            elif selected_item == 'run_hardcoded_function':
                  self.thread = QThread()
                  self.worker.moveToThread(self.thread)            
                  self.thread.started.connect(self.worker.run_hardcoded_algo)
                  self.thread.start()
            
            jsulmJ 1 Reply Last reply
            0
            • R robliou

              @JonB
              This is probably the cleanest way for me to explain the issue: seen below, I have a method called 'run_all_functions' in my Worker() class which allows the user to select which suite of algos to run based on the click of a button (attached to a dropdown menu within qt):

              import suite_1_algo_a, suite_1_algo_b, suite_1_algo_c
              import suite_2_algo_a, suite_2_algo_b, suite_2_algo_c
              
                  class Worker(QObject):
              
                      def run_all_functions(self):
                          if algo == 'suite_1':            
                                  test_a = suite_1_algo_a
                                  test_b = suite_1_algo_b
                                  test_c = suite_1_algo_c
                          if algo == 'suite_2':            
                                  test_a = suite_2_algo_a
                                  test_b = suite_2_algo_b
                                  test_c = suite_2_algo_c
              
                          result_1 = test_a.main
                          result_2 = test_b.main
                          result_3 = test_c.main
                    
                          print('result_1:', result_1 )
                          print('result_2:', result_2 )
                          print('result_3:', result_3)
              

              After selecting which suite to run, the pyqt Window will hang even as the selected function is running in the background. Whereas, if I simply create two separate functions with the values for test_a, test_b, and test_c hardcoded (i.e. no if/else option at the start for various algo scenarios), and then run either hardcoded function based on the press of a qt button, then the Window widget does not hang. Both the hardcoded and non-hardcoded functions are similarly initiated as threads, as follows:

              elif selected_item == 'run_hardcoded_function':
                    self.thread = QThread()
                    self.worker.moveToThread(self.thread)            
                    self.thread.started.connect(self.worker.run_hardcoded_algo)
                    self.thread.start()
              
              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @robliou Run in debugger and see where it hangs

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

              1 Reply Last reply
              1
              • R robliou

                @JonB

                Sure thing. Assume I have a method called 'run_all_tests' which runs 5 sub- tests:

                def run_all_tests(num_shots):
                   result_a = runTest_A(num_shots)
                   result_b = runTest_B(num_shots)
                   result_c = runTest_C(num_shots)
                   result_d = runTest_D(num_shots)
                   result_e = runTest_E(num_shots)
                

                if I call run_all_tests(100), then run_all_tests() will correctly pass the parameter 100 to each subtest and they all run fine in the background. However, in my qt Window widget it will hang (i.e I click anywhere on the window while it is running). Whereas, if I edit runTest_A, runTest_B, etc. such that the number of shots is hardcoded, and as such no parameter needs to be passed, as follows:

                def run_all_tests():
                   result_a = runTest_A()
                   result_b = runTest_B()
                   result_c = runTest_C()
                   result_d = runTest_D()
                   result_e = runTest_E()
                

                and then call run_all_tests(), then all 5 sub- functions again run properly in order, but with no qt Window hanging issues, even if I click somewhere on the Window itself.

                The way my run_all_tests() function is connected is as follows (note that the function launches on the event of a button click):

                ...
                elif selected_item == 'Multi-test':
                      self.thread = QThread()
                      self.worker.moveToThread(self.thread)                  
                      self.thread.started.connect(self.run_all_tests)
                      self.thread.start()            
                

                I'm open to any suggestions you may have, thank you.

                S Offline
                S Offline
                SimonSchroeder
                wrote on last edited by
                #7

                @robliou said in passing a parameter to a method causes Window to freeze:

                The way my run_all_tests() function is connected is as follows (note that the function launches on the event of a button click):

                The code you posted decribes how you call run_all_tests(). However, what are you doing to call run_all_tests(num_shots) when a button is clicked?

                R 1 Reply Last reply
                1
                • S SimonSchroeder

                  @robliou said in passing a parameter to a method causes Window to freeze:

                  The way my run_all_tests() function is connected is as follows (note that the function launches on the event of a button click):

                  The code you posted decribes how you call run_all_tests(). However, what are you doing to call run_all_tests(num_shots) when a button is clicked?

                  R Offline
                  R Offline
                  robliou
                  wrote on last edited by robliou
                  #8

                  @SimonSchroeder
                  Good question. For now, I'm just assuming that 'num_shots' = 100 for all tests and have hardcoded this into the run_all_tests() function, so that the variable does not need to be passed. As an example:

                  def run_all_tests(self):
                          num_shots = 100
                          #allows the cancel button to work
                          while self._is_running:
                              if not self.has_run:
                                 self.has_run = True
                                 self.result.emit('Running function #1- 
                   Simulated Annealing- 5 mins.')
                                 self.progress.emit(1)
                  
                                 result_x_1, result_y_1 = runTest_100_A.main(num_shots) 
                  
                                 self.result.emit('result_x_1: ' + result_x_1)   
                                 self.progress.emit(10)  # Emit signal to update progress bar to 10%
                                 self.counter += 1
                                 print('this is counter', self.counter)
                  
                                 # need this in front of each function in order to allow cancel button to work
                                 if not self._is_running:
                                      return
                  
                                 #run second algorithm
                                 result_x_2, result_y_2 = runTest_100_B.main(num_shots)
                                 self.result.emit('result_x_2: ' + result_x_2)   
                                 
                                 self.progress.emit(20)  # Emit signal to update progress bar to 20%
                                 
                                 self.counter += 1
                                 
                                 print('this is counter', self.counter)
                                 
                                 if not self._is_running:
                                 
                                     return
                  
                  

                  etc. (this repeats for all 10 algorithms until result_x_10, result_y_10 is reached). Note that the qt Window hanging usually begins around the time we reach result_x_5)

                  jsulmJ 1 Reply Last reply
                  0
                  • R robliou

                    @SimonSchroeder
                    Good question. For now, I'm just assuming that 'num_shots' = 100 for all tests and have hardcoded this into the run_all_tests() function, so that the variable does not need to be passed. As an example:

                    def run_all_tests(self):
                            num_shots = 100
                            #allows the cancel button to work
                            while self._is_running:
                                if not self.has_run:
                                   self.has_run = True
                                   self.result.emit('Running function #1- 
                     Simulated Annealing- 5 mins.')
                                   self.progress.emit(1)
                    
                                   result_x_1, result_y_1 = runTest_100_A.main(num_shots) 
                    
                                   self.result.emit('result_x_1: ' + result_x_1)   
                                   self.progress.emit(10)  # Emit signal to update progress bar to 10%
                                   self.counter += 1
                                   print('this is counter', self.counter)
                    
                                   # need this in front of each function in order to allow cancel button to work
                                   if not self._is_running:
                                        return
                    
                                   #run second algorithm
                                   result_x_2, result_y_2 = runTest_100_B.main(num_shots)
                                   self.result.emit('result_x_2: ' + result_x_2)   
                                   
                                   self.progress.emit(20)  # Emit signal to update progress bar to 20%
                                   
                                   self.counter += 1
                                   
                                   print('this is counter', self.counter)
                                   
                                   if not self._is_running:
                                   
                                       return
                    
                    

                    etc. (this repeats for all 10 algorithms until result_x_10, result_y_10 is reached). Note that the qt Window hanging usually begins around the time we reach result_x_5)

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

                    @robliou You are emitting signals. What are you doing in the slots connected to these signals? Your UI is probably hanging in one of these slots.
                    As already suggested debugger could also help.

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

                    R 1 Reply Last reply
                    0
                    • jsulmJ jsulm

                      @robliou You are emitting signals. What are you doing in the slots connected to these signals? Your UI is probably hanging in one of these slots.
                      As already suggested debugger could also help.

                      R Offline
                      R Offline
                      robliou
                      wrote on last edited by robliou
                      #10

                      @jsulm

                      Hi and Good question. So, at the top of my Worker() class, I have:

                          result = pyqtSignal(str)  # Signal emitted after each function with the result
                      

                      and then later on in my Main() class I have:

                              self.worker.result.connect(self.update_text_browser)
                      

                      this is the update_text_browser function:

                      def update_text_browser(self, result):
                              
                              self.textBrowser.insertHtml('<p align="left"><font face="Arial" color="black" size=3 ><b>'+ result + '</b></font><br></p>')  
                      

                      I'm assuming that all of this allows the emitted result to be displayed in my text_browser? 'result' is obviously successfully emitting to 'text_browser', but yes and weirdly, around the 4th or 5th emit the Window seems to hang... what could be the cause?

                      As for using debugger, are you referring to pdb? I tried implementing it, but it didn't seem to work unless I ran it from the Main() class (as opposed to Worker()), but running it from Main() resulted in an infinite loop and not the function itself running. I will try again, unless you are referring to another debugger specific to pyqt?

                      Thank you,

                      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