Results 1 to 14 of 14

Thread: QTimer / QThread question

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Apr 2010
    Posts
    17
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTimer / QThread question

    Thanks. Well, "VeryBad(TM)" sounds bad, so I guess I'll just emit signals with a QString argument to the gui instead. What I meant was make methods in the main qwdiget to change the contents and lock a mutex at the beginning of it and unlock at the end. That would protect everything inside in a rather crude way, and as long as that is the only method that changes those objects that would be sufficient, right? But then again, this still involves function calls to the gui from another thread. Is this inherently problematic?

    I think the slots must be running in the threadwatcher thread. Here's QThread::currentThread() at various points.

    main 0x6f51a8
    sw 0x6f51a8
    sorter 0x6f51a8
    tw-r 0x2222e40
    tw-h 0x2222e40

    Main creates a SortWindow (extends QWidget) and a Sorter (extends QObject) object. The latter has handlers for the buttons and such (I actually tried to make this a thread for awhile but realized this wasn't a great idea). The start button handler launched 6x sort threads and the threadWatcher thread. Tw-r is sampled in run() and Tw-h is in the finishedHandler slot. Pretty conclusive, no?

    Qt Code:
    1. void ThreadWatcher::run() {
    2. QTextStream cout(stdout, QIODevice::WriteOnly);
    3. cout << "tw-r " << QThread::currentThread() << endl;
    4. QSignalMapper threadMapper;
    5. updateTimer = new QTimer();
    6.  
    7. for (int i = 0; i < 6; i++) {
    8. connect(thread[i], SIGNAL(finished()), &threadMapper, SLOT(map()));
    9. threadMapper.setMapping(thread[i], i);}
    10.  
    11. connect(&threadMapper, SIGNAL(mapped(int)), this, SLOT(finishedHandler(int)));
    12. connect(updateTimer, SIGNAL(timeout()), this, SLOT(timeoutHandler()));
    13.  
    14. connect(this, SIGNAL(refresh(int)), window, SLOT(draw(int)));
    15.  
    16. updateTimer->start(timerVal);
    17.  
    18. QThread::exec();
    19.  
    20. delete updateTimer;
    21. }
    22. void ThreadWatcher::timeoutHandler() {
    23.  
    24. for(int i=0; i<6; i++) {
    25. if (alive[i])
    26. emit refresh(i); }
    27.  
    28. if ((threadsLeft==0) || (control[1])) {
    29. QThread::exit(0); }
    30.  
    31. else if (control[0]) {
    32. lock->lock();
    33. updateTimer->stop();
    34. condition->wait(lock);
    35. lock->unlock();
    36. updateTimer->start(timerVal); }
    37. }
    38. void ThreadWatcher::finishedHandler(int t) {
    39. QTextStream cout(stdout, QIODevice::WriteOnly);
    40. cout << "tw-h " << QThread::currentThread() << endl;
    41. emit refresh(t);
    42. alive[t] = false;
    43. threadsLeft--;
    44.  
    45. seconds[t] = (float)runTime[t] / 1000.0f;
    46. if (seconds[t] == 0.0f)
    47. seconds[t] = 0.001f;
    48. time[t]->setText("Time: "+QString::number(seconds[t],'g',3));
    49. if (isFirst) {
    50. isFirst = false;
    51. long minTime = runTime[t];
    52. min = t;
    53. long x;
    54.  
    55. for (int k=0; k<6; k++) {interval)
    56. x = runTime[k];
    57. if ((x > -1) && (x < minTime)) {
    58. minTime = x;
    59. min = k; } }
    60.  
    61. if (min != t) {
    62. seconds[min] = (float)runTime[min] / 1000.0f;
    63. if (seconds[min] == 0.0f)
    64. seconds[min] = 0.001f; }
    65.  
    66. if (min == t)
    67. ratio[t]->setText("Ratio: 1x");
    68. else {
    69. ratio[t]->setText("Ratio: "+QString::number(seconds[t]/seconds[min],'g',3)+"x"); } }
    70.  
    71. else
    72. ratio[t]->setText("Ratio: "+QString::number(seconds[t]/seconds[min],'g',3)+"x");
    73. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by Galen; 19th April 2010 at 23:04.

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

    Default Re: QTimer / QThread question

    Quote Originally Posted by Galen View Post
    What I meant was make methods in the main qwdiget to change the contents and lock a mutex at the beginning of it and unlock at the end. That would protect everything inside in a rather crude way, and as long as that is the only method that changes those objects that would be sufficient, right?
    Unfortunately not. This protects code, not the shared resource. Qt will still access the widget from within other methods "behind your back" and you can't protect that.

    But then again, this still involves function calls to the gui from another thread. Is this inherently problematic?
    Yes, GUI resources just can't be protected from within application code.

    I think the slots must be running in the threadwatcher thread. Here's QThread::currentThread() at various points.
    The thread-watcher thread is redundant - all it does is to monitor other threads so it can be done from the main thread.

    Take a look at QtConcurrent and especially QFutureWatcher, by the way.

  3. #3
    Join Date
    Apr 2010
    Posts
    17
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTimer / QThread question

    Well, true, but its my redundant thread and I love it. Plus I want to use emit in this code somewhere. So now I've stripped out all the function calls. The emit signal system is really pretty much the same thing so no biggie. Everything seems to be running pretty well now, the inline function at the bottom fixes a problem whereby threads with longer running time somehow end up signalling first.

    Thanks, I'll take a look at those classes, but this isn't even a real app so I probably won't be switching over even if it would run better. For this code sample I'm pretty much assuming an unlimited number of cores.


    Qt Code:
    1. void ThreadWatcher::run() {
    2. QSignalMapper threadMapper;
    3. updateTimer = new QTimer();
    4.  
    5. for (int i = 0; i < 6; i++) {
    6. connect(thread[i], SIGNAL(finished()), &threadMapper, SLOT(map()));
    7. threadMapper.setMapping(thread[i], i); }
    8.  
    9. connect(&threadMapper, SIGNAL(mapped(int)), this, SLOT(finishedHandler(int)));
    10. connect(updateTimer, SIGNAL(timeout()), this, SLOT(timeoutHandler()));
    11. connect(this, SIGNAL(refresh(int)), window, SLOT(draw(int)));
    12. connect(this, SIGNAL(time(int, QString)), window, SLOT(setTimeLabel(int, QString)));
    13. connect(this, SIGNAL(ratio(int, QString)), window, SLOT(setRatioLabel(int, QString)));
    14.  
    15. updateTimer->start(timerVal);
    16.  
    17. QThread::exec();
    18.  
    19. delete updateTimer;
    20. }
    21. void ThreadWatcher::timeoutHandler() {
    22.  
    23. for(int i=0; i<6; i++) {
    24. if (alive[i])
    25. emit refresh(i); }
    26.  
    27. if ((threadsLeft==0) || (control[1])) {
    28. QThread::exit(0); }
    29.  
    30. else if (control[0]) {
    31. updateTimer->stop();
    32. lock->lock();
    33. condition->wait(lock);
    34. lock->unlock();
    35. updateTimer->start(timerVal); }
    36. }
    37. void ThreadWatcher::finishedHandler(int t) {
    38. emit refresh(t);
    39. alive[t] = false;
    40. threadsLeft--;
    41.  
    42. seconds[t] = (float)runTime[t] / 1000.0f;
    43. if (seconds[t] == 0.0f)
    44. seconds[t] = 0.001f;
    45. emit time(t, "Time: "+QString::number(seconds[t],'g',3));
    46.  
    47. if (isFirst) {
    48. isFirst = false;
    49. min = t;
    50. emit ratio(t, "Ratio: 1x"); }
    51. else {
    52. float timeRatio = seconds[t]/seconds[min];
    53. if (timeRatio < 1.0f)
    54. fixRatios(t);
    55. else
    56. emit ratio(t, "Ratio: "+QString::number(timeRatio,'g',3)+"x"); }
    57. }
    58. inline void ThreadWatcher::fixRatios(int t) {
    59. long minTime = runTime[min];
    60. long x;
    61.  
    62. for (int i=0; i<6; i++) {
    63. if (!alive[i]) {
    64. x = runTime[i];
    65. if ((x > -1) && (x < minTime)) {
    66. minTime = x;
    67. min = i; } } }
    68.  
    69. for (int j=0; j<6; j++) {
    70. if (!alive[j]) {
    71. if (j==min)
    72. emit ratio(j, "Ratio: 1x");
    73. else
    74. emit ratio(j, "Ratio: "+QString::number(seconds[j]/seconds[min],'g',3)+"x"); } }
    75. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. QThread and QTimer
    By sivrisinek in forum Qt Programming
    Replies: 4
    Last Post: 30th April 2009, 16:41
  2. QThread & QTimer
    By hosseinyounesi in forum Qt Programming
    Replies: 5
    Last Post: 13th April 2009, 08:22
  3. QTimer and QThread in Qtopia 4.2.0
    By mellibra in forum Qt for Embedded and Mobile
    Replies: 3
    Last Post: 25th October 2007, 08:26
  4. QTimer and QThread
    By TheKedge in forum Qt Programming
    Replies: 4
    Last Post: 21st September 2006, 14:52
  5. Qthread n QTimer Problem
    By quickNitin in forum Qt Programming
    Replies: 5
    Last Post: 8th June 2006, 14:12

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
  •  
Qt is a trademark of The Qt Company.