Results 1 to 12 of 12

Thread: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

  1. #1
    Join Date
    Mar 2012
    Posts
    10
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    I have the following code:
    Qt Code:
    1. from PySide.QtCore import *
    2. import time
    3.  
    4. class GUI(object):
    5.  
    6. IDLIST = [i for i in xrange(20)]
    7. UNUSEDIDS = [i for i in xrange(20)]
    8.  
    9. def __init__(self):
    10. print "GUI CLASS INITIALIZED!"
    11.  
    12. worker = Worker()
    13. worker2 = Worker2()
    14.  
    15. threadpool = QThreadPool()
    16. threadpool.setMaxThreadCount(10)
    17.  
    18. for i in xrange(5):
    19. #Alternate between the two
    20. #threadpool.start(worker)
    21. #worker2.start()
    22.  
    23.  
    24. @classmethod
    25. def delegator(self):
    26. """Irrelevant to the question, I need this method for something else"""
    27. USEDIDS = []
    28.  
    29. toUse = self.UNUSEDIDS[0]
    30. USEDIDS.append(toUse)
    31. self.UNUSEDIDS.pop(0)
    32.  
    33. return toUse
    34.  
    35.  
    36. class Worker(QRunnable):
    37.  
    38. def __init__(self, parent=None):
    39. super(Worker, self).__init__(parent)
    40.  
    41. def run(self):
    42. #idInUse = getattr(GUI, "delegator")
    43. idInUse = GUI.delegator()
    44. print "Hello world from QRunnable", idInUse
    45. #time.sleep(5)
    46.  
    47. class Worker2(QThread):
    48.  
    49. def __init__(self, parent=None):
    50. super(Worker2, self).__init__(parent)
    51.  
    52. def run(self):
    53. idInUse = GUI.delegator()
    54. print "Hello world from QThread", idInUse
    55.  
    56.  
    57. s = time.time()
    58. GUI()
    59. print "Done in %s" % ((time.time()-s) * 1000)
    To copy to clipboard, switch view to plain text mode 

    I think the desired effect is obvious from the code. I want the "Hello world from QThread/QRunnable " to be shown. Since I am writing a multi-threaded application, in my GUI __init__ part I have the loop that starts concurrent threads.

    The thing is that, with QRunnable it works just fine. All the 5 threads I specified get executed at once, concurrently. With QThread, however, that is not the case. Instead, I get the following error:

    Qt Code:
    1. QThread: Destroyed while thread is still running
    To copy to clipboard, switch view to plain text mode 

    And it is not executed at all.

    Normally I would not at all mind using the QRunnable, however, it does not derive from QObject (so I can't directly emit signals though I can construct a QObject() within it) and also it does not have the .stop() method which I badly need. Googling revealed that there is no way to stop a QRunnable from executing? On the other hand, QThread has both of these methods that I need.

    So I guess my question is either how to make multiple same QThreads run concurrently, or how to terminate an execution of a QRunnable?

  2. #2
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    why cant you just make and use several QThread instances?
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  3. #3
    Join Date
    Mar 2012
    Posts
    10
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    You mean why not make them all separate classes? Well, one because I need them all to be identical (except for some small parts that that Delegator() method decides) and two because I need to create hundreds of such threads.

  4. #4
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    no, I said instances, not classes.
    Qt Code:
    1. for i in xrange(5):
    2. #Alternate between the two
    3. #threadpool.start(worker)
    4. #worker2.start() # no, this is wrong
    5. wrk2 = Worker2() # make a new Worker2.
    6. wrk2.start() # you cant expect 'start()' to work properly if the thread is till running...
    To copy to clipboard, switch view to plain text mode 


    You know you dont *need* to inherit from QThread in order to have the work done *in* the thread?
    Last edited by amleto; 15th May 2012 at 09:26.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  5. #5
    Join Date
    Mar 2012
    Posts
    10
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    Oh sorry about that - yes I tried that too. The result is:

    Qt Code:
    1. GUI CLASS INITIALIZED!!!
    2. Done in 3.00002098083
    3. QThread: Destroyed while thread is still running
    4. QThread: Destroyed while thread is still running
    5. QThread: Destroyed while thread is still running
    6. QThread: Destroyed while thread is still running
    7. QThread: Destroyed while thread is still running
    To copy to clipboard, switch view to plain text mode 

    If I add a .wait() in that for loop, it works, but then it is not really concurrent.

    And yes I am aware that I don't need to inherit from QThread, but I need to... I mean, the rest of the application requires me to (don't ask).

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    What if you change "worker2" to "self.worker2" (that is make it an object member)?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Mar 2012
    Posts
    10
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    Same thing happens

  8. #8
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    Quote Originally Posted by Deusdies View Post
    Oh sorry about that - yes I tried that too. The result is:

    Qt Code:
    1. GUI CLASS INITIALIZED!!!
    2. Done in 3.00002098083
    3. QThread: Destroyed while thread is still running
    4. QThread: Destroyed while thread is still running
    5. QThread: Destroyed while thread is still running
    6. QThread: Destroyed while thread is still running
    7. QThread: Destroyed while thread is still running
    To copy to clipboard, switch view to plain text mode 

    If I add a .wait() in that for loop, it works, but then it is not really concurrent.

    And yes I am aware that I don't need to inherit from QThread, but I need to... I mean, the rest of the application requires me to (don't ask).
    please show your code that does this. If truly is different instances that are being destroyed then it must be the GC, which seems unlikely.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  9. #9
    Join Date
    Mar 2012
    Posts
    10
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    It isn't any different from the one I gave already, except for the instance creation part...

    Qt Code:
    1. from PySide.QtCore import *
    2. import time
    3.  
    4. class GUI(object):
    5.  
    6. IDLIST = [i for i in xrange(20)]
    7. UNUSEDIDS = [i for i in xrange(20)]
    8.  
    9. def __init__(self):
    10. print "GUI CLASS INITIALIZED!"
    11.  
    12. worker = Worker()
    13. worker2 = Worker2()
    14.  
    15. threadpool = QThreadPool()
    16. threadpool.setMaxThreadCount(10)
    17.  
    18. for i in xrange(5):
    19. #Tried:
    20. #worker2 = Worker2()
    21. #worker2.start()
    22. #...and...
    23. #self.worker2 = Worker2()
    24. #self.worker2.start()
    25.  
    26.  
    27. @classmethod
    28. def delegator(self):
    29. """Irrelevant to the question, I need this method for something else"""
    30. USEDIDS = []
    31.  
    32. toUse = self.UNUSEDIDS[0]
    33. USEDIDS.append(toUse)
    34. self.UNUSEDIDS.pop(0)
    35.  
    36. return toUse
    37.  
    38.  
    39. class Worker(QRunnable):
    40.  
    41. def __init__(self, parent=None):
    42. super(Worker, self).__init__(parent)
    43.  
    44. def run(self):
    45. #idInUse = getattr(GUI, "delegator")
    46. idInUse = GUI.delegator()
    47. print "Hello world from QRunnable", idInUse
    48. #time.sleep(5)
    49.  
    50. class Worker2(QThread):
    51.  
    52. def __init__(self, parent=None):
    53. super(Worker2, self).__init__(parent)
    54.  
    55. def run(self):
    56. idInUse = GUI.delegator()
    57. print "Hello world from QThread", idInUse
    58.  
    59.  
    60. s = time.time()
    61. GUI()
    62. print "Done in %s" % ((time.time()-s) * 1000)
    To copy to clipboard, switch view to plain text mode 

  10. #10
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    oh, the problem is the way you close the threads! (I think)


    close them more politely (call quit() / wait()) instead of ignoring them and letting end of program clean them up.
    Last edited by amleto; 16th May 2012 at 00:14.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  11. #11
    Join Date
    Mar 2012
    Posts
    10
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    Now I'm getting some very interesting results.

    First run output:
    Qt Code:
    1. GUI CLASS INITIALIZED!!!
    2. Done in 2.99009998083
    3. QThread: Destroyed while thread is still running
    4. QThread: Destroyed while thread is still running
    5. QThread: Destroyed while thread is still running
    6. QThread: Destroyed while thread is still running
    7. QThread: Destroyed while thread is still running
    To copy to clipboard, switch view to plain text mode 

    Second run output:
    Qt Code:
    1. GUI CLASS INITIALIZED!!!
    2. UNUSEDIDS [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    3. Hello world from QThread 0
    4. UNUSEDIDS [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    5. Hello world from QThread 1
    6. QThread: Destroyed while thread is still running
    7. QThread: Destroyed while thread is still running
    8. UNUSEDIDS [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    9. Hello world from QThread 2
    10. Done in 13.9999389648
    To copy to clipboard, switch view to plain text mode 

    Third run output
    Qt Code:
    1. GUI CLASS INITIALIZED!!!
    2. UNUSEDIDS UNUSEDIDS[ UNUSEDIDS0[ , 0[1, 0, 1, 2, 1, 2, 3UNUSEDIDS, 2, 3, 4[, 3, 04, 5UNUSEDIDS, , 4, Done in 2.00009346008 15, 6
    3. [, , 5, 026, 7, , , 6,
    To copy to clipboard, switch view to plain text mode 

    Fourth run output
    Qt Code:
    1. GUI CLASS INITIALIZED!!!
    2. UNUSEDIDS [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    3. Hello world from QThread 0
    4. UNUSEDIDS [1, 2, 3, 4, 5, 6, UNUSEDIDS7 , [Done in 3.9999485015981
    5. , , QThread: Destroyed while thread is still running
    6. QThread: Destroyed while thread is still running
    7. 92, , 10
    To copy to clipboard, switch view to plain text mode 

    Fifth run output the python.exe crashed (Windows displayed the "not responding" message).

    What's obvious is that there are different results from every single run. This prompted me to believe that either there's a problem with GC, or that there's an actual bug in Qt.

    It crossed my mind to do the following:
    Qt Code:
    1. self.workers = [Worker2(),Worker2(),Worker2(),Worker2(),Worker2()]
    2. for i in xrange(5):
    3. self.workers[i].start()
    4. time.sleep(0.01)
    To copy to clipboard, switch view to plain text mode 
    In other words, sleep for 10 miliseconds after every thread start. Interestingly enough, this (sort-of) worked. Here's the result I got every time after 5 runs:

    Qt Code:
    1. GUI CLASS INITIALIZED!!!
    2. UNUSEDIDS [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    3. Hello world from QThread 0
    4. UNUSEDIDS [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    5. Hello world from QThread 1
    6. UNUSEDIDS [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    7. Hello world from QThread 2
    8. UNUSEDIDS [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    9. Hello world from QThread 3
    10. UNUSEDIDS [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    11. Hello world from QThread 4
    12. Done in 49.9999523163
    To copy to clipboard, switch view to plain text mode 

    While not quite as efficient as the QRunnable equivalent (which gets done in 10 ms but this is because the QRunnable's for loop does not have the time.sleep at the end), it's better than nothing. Since my application will be limited to 20 (30) threads at most, the performance impact should be negligible.

    I've also noticed that if I reduce the sleep() period to 1 milisecond, the code becomes much more unstable; while it worked fine the first 3 runs, it crashed the interpreter on the 4th run. I am assuming that the higher the value of the sleep is, the more stable the code will be.

  12. #12
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Concurrent execution of QThread or QRunnable (also how to terminate the latter?)

    no, you should not be hacking a fix that only addresses the symptoms.

    As I say, the problem is at close down - you need to save a handle to all QThreads, and then call wait/quit/terminate on them when you have done everything else in the main thread:

    Qt Code:
    1. class GUI(object):
    2. def join(self):
    3. for w in self.workers:
    4. w.wait()
    5. ...
    6.  
    7. s = time.time()
    8. g = GUI()
    9. g.join()
    10. print "Done in %s" % ((time.time()-s) * 1000)
    To copy to clipboard, switch view to plain text mode 
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

Similar Threads

  1. terminate a QThread from GUI
    By OverTheOCean in forum Qt Programming
    Replies: 6
    Last Post: 26th July 2010, 02:12
  2. Terminate a QThread with an event loop
    By paolom in forum Qt Programming
    Replies: 2
    Last Post: 12th May 2010, 11:53
  3. QRunnable - how to cancel execution?
    By TorAn in forum Qt Programming
    Replies: 1
    Last Post: 3rd March 2010, 19:11
  4. QThread::terminate () is not working!!!!!
    By biswajithit in forum Qt Programming
    Replies: 1
    Last Post: 15th September 2008, 12:03
  5. Replies: 4
    Last Post: 27th July 2006, 11:13

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.