Results 1 to 7 of 7

Thread: Yet another another multithreading problem!

  1. #1
    Join Date
    Feb 2009
    Posts
    11
    Thanks
    4
    Qt products
    Platforms
    Unix/X11 Windows

    Default Yet another another multithreading problem!

    Hi,
    Even if you're not familiar with python, I don't think you would have any trouble understanding this code:
    Qt Code:
    1. from PyQt4.QtCore import *
    2. from PyQt4.QtGui import *
    3. import sys
    4. from time import sleep
    5.  
    6. class Thread(QThread):
    7. def __init__(self, parent):
    8. QThread.__init__(self, parent)
    9. self.lock = QReadWriteLock()
    10. def run(self):
    11. self.stopped = False
    12. self.timer = QTimer()
    13. self.connect(self.timer, SIGNAL("timeout()"), self.timeout)
    14. self.timer.start(200)
    15. self.exec_()
    16. def stop(self):
    17. with QWriteLocker(self.lock):
    18. self.stopped = True
    19. def timeout(self):
    20. with QReadLocker(self.lock):
    21. if not self.stopped:
    22. sleep(0.4) #400 miliseconds
    23. #Here's actually a piece of code which I can't estimate
    24. #deterministically how long it takes.
    25. else:
    26. self.timer.stop()
    27. class Form(QDialog):
    28. def __init__(self, parent = None):
    29. QDialog.__init__(self, parent)
    30. self.resize(352, 288)
    31. self.thread = Thread(self)
    32. self.thread.start()
    33. def closeEvent(self, event):
    34. self.thread.stop()
    35. self.thread.quit()
    36. event.accept()
    To copy to clipboard, switch view to plain text mode 
    The problem is that, even the time-consuming procedure is placed in a thread other than the main (GUI) thread, the program will be frozen after 3-4 seconds in runtime and then you have to go straight to the task manager in order to close it!
    As you might have guessed, there's something wrong in this code:

    Qt Code:
    1. ~~> self.timer.start(200)
    2. ################
    3. ~~> sleep(0.4)
    To copy to clipboard, switch view to plain text mode 

    Yeah, the timeout method takes at least 400 milliseconds to run, while we set the interval to 200 milliseconds. Well, I'm not a masochistic kind of person! Actually there is a snippet of code in the timeout method which does the following tasks:

    1- Acquiring a frame from a web cam through OpenCV
    2- Invoking face detection procedure
    3- Calling a C-implemented function to convert IplImage to a format suitable for QImage.

    This operation should be run periodically. I can't guess the time it needs to accomplish these tasks while it depends on many factors, like system load and the type of platform. And it may take longer than the period I set as the interval of QTimer.
    Yeah I know that I should take another approach, but why the operation which is running in the thread, affects the main thread? Why does it slow down the main thread? And if it was supposed to behave so, what's the point of having a thread?!
    Oh, btw, The following is part of 'Programming with Qt' by Matthias Kalle Dalheimer which stands that it's not a good idea to instantiate the QTimer class in any thread other than the main thread which I've found very common among Qt programmers:
    http://books.google.com/books?id=1-Q...age&q=&f=false
    * Timers and their events always belong in the GUI thread.
    * Never create any objects of subclasses of QWidget, QTimer and QSocketNotifier in anything other than the main thread – not even when Qt is locked. Some Operating Systems will allocate the memory for these objects in a way that makes them inaccessible from the other threads.
    Sorry for my bad english
    Last edited by nimaweb; 11th August 2009 at 01:53.

  2. #2
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Yet another another multithreading problem!

    From QTimer's docs (Qt 4.5.2)
    In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.
    maybe that book is on Qt3?

    anyway, just as in the gui thread, if your long running job is running, the threads event loop does not get to process events

  3. #3
    Join Date
    Feb 2009
    Posts
    11
    Thanks
    4
    Qt products
    Platforms
    Unix/X11 Windows

    Default Re: Yet another another multithreading problem!

    Quote Originally Posted by caduel View Post
    From QTimer's docs (Qt 4.5.2)

    maybe that book is on Qt3?

    anyway, just as in the gui thread, if your long running job is running, the threads event loop does not get to process events
    Yeah, you are right. That book covers Qt3. That was very inconsiderate of me.
    But how do you suggest I do this without needing to have a QTimer. I want my timeout method to be called periodically and I can't determine an appropriate value for the QTimer's interval to have a well-behaved thread.
    Maybe I shouldn't call QThread::exec() at all. I think I can have a 'forever' loop in the run() method of the thread which calls the sleep() function after every single frame it captures. What do you think?

  4. #4
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Yet another another multithreading problem!

    lots of possibilities...

    Maybe I'd make a slot grabFrame() in the thread class, that slot could emit the grabbed frame by a signal.
    Each grabbing could trigger a singleshot timer to trigger the next frame to be captured after some delay.
    This design would also feature an event loop.
    (An advantage would be that, using signal/slot to communicate with the thread) you would not need to worry about how to pass grabbed frames.)

    An altogether different (maybe easier way) would be to do the grabbing with QFuture (read up on Qt Concurrent) and handle the timer class in the gui thread.

    HTH

  5. The following user says thank you to caduel for this useful post:

    nimaweb (11th August 2009)

  6. #5
    Join Date
    Feb 2009
    Posts
    11
    Thanks
    4
    Qt products
    Platforms
    Unix/X11 Windows

    Default Re: Yet another another multithreading problem!

    QFuture is not implemented in PyQt. I think i'll stick with the processing-each-frame-triggers-another-frame-processing-after-some-delay idea.
    Is there anyone familiar with python and it's GIL(Global Interpreter Lock)? Do you think that it would be related to my problem? Does the code above act similar when it's implemented in C++? Is it wrong to ask such questions here?

  7. #6
    Join Date
    Feb 2009
    Posts
    11
    Thanks
    4
    Qt products
    Platforms
    Unix/X11 Windows

    Post Re: Yet another another multithreading problem!

    I forgot to tell you that I've modified the thread and it works just fine (thanks to caduel):
    Qt Code:
    1. class Thread(QThread):
    2. def __init__(self, parent):
    3. QThread.__init__(self, parent)
    4. self.lock = QReadWriteLock()
    5. def run(self):
    6. self.stopped = False
    7. while True:
    8. with QReadLocker(self.lock):
    9. if not self.stopped:
    10. print "Hi there!"
    11. #Here's actually a piece of code which I can't estimate
    12. #deterministically how long it takes.
    13. sleep(0.4) #delay
    14. else:
    15. break
    16. def stop(self):
    17. with QWriteLocker(self.lock):
    18. self.stopped = True
    To copy to clipboard, switch view to plain text mode 
    You can dynamically increase or decrease the delay depending on the execution time of the procedure.
    Last edited by nimaweb; 11th August 2009 at 14:04.

  8. #7
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Yet another another multithreading problem!

    btw, guarding a bool with a mutex in not really necessary:
    if it is false, ok; if you set it to true, while the other thread is reading it... what can happen?
    either it gets false (which is absolutely ok...you can't influence timing anyway), or it gets the new value... (The idea is that (at least in C++) you can probably assume that a bool changes atomically...)

Similar Threads

  1. Another multithreading problem
    By Sheng in forum Qt Programming
    Replies: 4
    Last Post: 31st October 2008, 13:14
  2. Problem in using QHttp with QTimer
    By Ferdous in forum Newbie
    Replies: 2
    Last Post: 6th September 2008, 12:48
  3. [QMYSQL] connection problem
    By chaos_theory in forum Installation and Deployment
    Replies: 5
    Last Post: 2nd July 2007, 09:52
  4. Grid Layout Problem
    By Seema Rao in forum Qt Programming
    Replies: 2
    Last Post: 4th May 2006, 12:45
  5. fftw problem
    By lordy in forum General Programming
    Replies: 1
    Last Post: 16th March 2006, 21:36

Tags for this Thread

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.