Results 1 to 16 of 16

Thread: Shutting down threads prematurely

  1. #1
    Join Date
    Oct 2015
    Posts
    33
    Thanks
    14
    Qt products
    Qt5
    Platforms
    Unix/X11

    Question Shutting down threads prematurely

    hey guys,

    my app does calculations in backround threads which are contained in a worker object. The calculations performed are long and sometimes i will want to shut down the calculations and restart them. I wanted to let the main gui connect to the worker and tell it to terminate its current thread but somehow i cant get it to work.

    from mainwindow.cpp:

    creating threads and connecting them + start thread

    Qt Code:
    1. for (int id=1;id<=guidata.numbers_of_workerthreads;id++)
    2. {
    3.  
    4. QThread *thread = new QThread;
    5.  
    6. Worker *worker = new Worker(&guidata,ui,id,&m_c,&mutex_file,&mutex_count);
    7.  
    8. worker->moveToThread(thread);
    9.  
    10. //connect events from worker<-> threads
    11. connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
    12. connect(thread, SIGNAL(started()), worker, SLOT(comets_to_use()));
    13. connect(this, SIGNAL(shut_down_threads()), worker ,SLOT(on_shut_down_threads())); //<--- how im trying to access thread/worker from gui
    14. connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    15. connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    16. connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    17.  
    18. thread->start();
    19. }
    20. }
    To copy to clipboard, switch view to plain text mode 

    this button is pressed to initiate the threads to shut down;

    Qt Code:
    1. //stop button
    2. void MainWindow::on_pushButton_9_clicked()
    3. {
    4.  
    5. qDebug() << "shutdown emitted";
    6. emit shut_down_threads();
    To copy to clipboard, switch view to plain text mode 

    from worker.cpp:
    (i know terminate is a bad practice this is just to get the initial shutdown to work)

    Qt Code:
    1. void Worker::on_shut_down_threads()
    2. {
    3. qDebug() << "terminating thread " << QString::number(thread_id);
    4. QThread::currentThread()->terminate();
    5. }
    To copy to clipboard, switch view to plain text mode 

    sadly this is not stopping my calculations. Any pointers where i went wrong? im kinda lost! thx boys.

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Shutting down threads prematurely

    Cross-Thread Signal/Slot connections (or more precisely Qt::QueuedConnection type connections) require a running event loop in the receiver object's thread.

    Theoretically that is the case, as QThread::run's base implementation runs an event loop.
    However, if comets_to_use() slot is the long running operation, then the event loop isonly ever executing that slot, the shutdown will be queued until that first slot ends.

    What you need is a method on the worker object that is being called by the main thread, e.g. using signal/slot but using a Qt::DirectConnection.
    Obviously you can't use QThread::currentThread() in that method since that will be executed by the main thread :-)

    Cheers,
    _

  3. The following user says thank you to anda_skoa for this useful post:

    Lumbricus (21st March 2016)

  4. #3
    Join Date
    Oct 2015
    Posts
    33
    Thanks
    14
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Shutting down threads prematurely

    Thx anda for pointing me in the right direction. I was not aware i'm blocking the eventloop of my threads with that long-ass slot.

    So i tried your approach with the use of a direct connection.

    Qt Code:
    1. connect(this, SIGNAL(shut_down_threads()), worker ,SLOT(on_shut_down_threads()),Qt::DirectConnection);
    To copy to clipboard, switch view to plain text mode 

    this works and instantly calls the slot in the worker. when i press my stop button. BUT

    output:

    shutdown emitted
    terminating thread "1"
    terminate called without an active excemption
    The program has unexpectedly finished.

    so i tried changing the command from terminate() of the thread to prematurely

    Qt Code:
    1. emit finished();
    To copy to clipboard, switch view to plain text mode 

    but that had no effect. I thought i might just be able to call the normal destruction chain when my worker finishes, but no luck.

    next try was to change the terminate() to:

    Qt Code:
    1. QThread::currentThread()->quit();
    To copy to clipboard, switch view to plain text mode 

    output:
    shutdown emitted
    terminated thread "1"
    terminated thread "2"
    ... /imex exited with code 0

    So the currentThread() statement is called in the "worker threads" but it also quits my main thread. Now i'm confused. I saw something you posted in 2015 where you were saying something about directconnections calling the slot in the thread where it was emitted...is this the case her? Thx anda you've been helping me a lot.

  5. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Shutting down threads prematurely

    Quote Originally Posted by Lumbricus View Post
    I was not aware i'm blocking the eventloop of my threads with that long-ass slot.
    Any thread can only execute one code path at any given time.

    Quote Originally Posted by Lumbricus View Post
    this works and instantly calls the slot in the worker. when i press my stop button. BUT

    output:

    shutdown emitted
    terminating thread "1"
    terminate called without an active excemption
    The program has unexpectedly finished.
    Maybe you forgot to replace the QThread::currentThread() with somethng to access the worker thread?

    so i tried changing the command from terminate() of the thread to prematurely

    Quote Originally Posted by Lumbricus View Post
    Qt Code:
    1. emit finished();
    To copy to clipboard, switch view to plain text mode 

    but that had no effect. I thought i might just be able to call the normal destruction chain when my worker finishes, but no luck.
    You are using delayed deletion via deleteLater(), so again after the thread's event loop had a chance to process events.


    Quote Originally Posted by Lumbricus View Post
    next try was to change the terminate() to:

    Qt Code:
    1. QThread::currentThread()->quit();
    To copy to clipboard, switch view to plain text mode 
    In a slot executed by the worker thread, right?
    Not in on_shut_down_threads(), right?

    Quote Originally Posted by Lumbricus View Post
    So the currentThread() statement is called in the "worker threads" but it also quits my main thread.
    How did you do the thread transition?

    Quote Originally Posted by Lumbricus View Post
    I saw something you posted in 2015 where you were saying something about directconnections calling the slot in the thread where it was emitted...is this the case her?
    Yes, I even wrote that in my other reply here, last sentence.

    My recommendation would be to derive from QThread and reimplement run() instead.
    Much more obvious which thread does what.

    Cheers,
    _

  6. #5
    Join Date
    Oct 2015
    Posts
    33
    Thanks
    14
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Shutting down threads prematurely

    Hey,

    on_shut_down_threads() is a slot of the worker that was moved to the new thread. So it lives in the worker thread. So accessing currentThread() <- is the worker thread.

    I have like 15 methods/slots of the worker to do different kind of work. I would have to reimplement a derived thread run() for all of them right?

    Is there a way to unblock the eventloop of the thread...like just making the slot call a function and then carry on looping?

  7. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Shutting down threads prematurely

    Quote Originally Posted by Lumbricus View Post
    on_shut_down_threads() is a slot of the worker that was moved to the new thread. So it lives in the worker thread. So accessing currentThread() <- is the worker thread.
    Ah, I thought you had connected that slot with a Qt::DirectConnection.

    Quote Originally Posted by Lumbricus View Post
    I have like 15 methods/slots of the worker to do different kind of work. I would have to reimplement a derived thread run() for all of them right?
    Ah, so you have many methods like "comets_to_use()" and you call them from different trigger signals form the main thread?

    Quote Originally Posted by Lumbricus View Post
    Is there a way to unblock the eventloop of the thread...like just making the slot call a function and then carry on looping?
    You can get the thread's event dispatcher and call its processEvents() now and then, but be aware that this leads to re-entrancy-like behavior even withing a single thread.

    Cheers,
    _

  8. #7
    Join Date
    Oct 2015
    Posts
    33
    Thanks
    14
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Shutting down threads prematurely

    Ah, I thought you had connected that slot with a Qt::DirectConnection.
    this is the code posted earlier, signal is connected to worker object slot, in worker thread;

    Qt Code:
    1. connect(this, SIGNAL(shut_down_threads()), worker ,SLOT(on_shut_down_threads()),Qt::DirectConnection);
    To copy to clipboard, switch view to plain text mode 

    Ah, so you have many methods like "comets_to_use()" and you call them from different trigger signals form the main thread?
    yes i have different methods like comets_to_use.

    In the beginning I had a different approach i tried. It was keeping the pointers to the created threads and trying to tell the threads do exit from the main thread. I had something like this:

    Qt Code:
    1. for (int i=0,i<number of threads,i++)
    2. {
    3. QThread *thread = new QThread;
    4. //save pointer
    5. active_threads[i] = thread;
    6.  
    7. //then do worker object set up and move it to thread and start thread.
    8. ....
    9. }
    To copy to clipboard, switch view to plain text mode 
    and then when i click the button run something like this:

    Qt Code:
    1. emit active_threads[i]->quit();
    2. //
    3. active_threads[i]->terminate;
    To copy to clipboard, switch view to plain text mode 

    it didn't seem to work would that be a better approach? or am i making an obvious mistake? Is this also blocked by the long executing slot in the worker?
    Last edited by Lumbricus; 21st March 2016 at 12:30.

  9. #8
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Shutting down threads prematurely

    Quote Originally Posted by Lumbricus View Post
    this is the code posted earlier, signal is connected to worker object slot, in worker thread;

    Qt Code:
    1. connect(this, SIGNAL(shut_down_threads()), worker ,SLOT(on_shut_down_threads()),Qt::DirectConnection);
    To copy to clipboard, switch view to plain text mode 
    Ok, now I am afraid I can't follow.
    You call the slot via a direct connection, so you are no longer using QThread::currentThread() in that slot, right?
    So are you somehow making the other thread execute some code or are you using a different approach to get the thread pointer?


    Quote Originally Posted by Lumbricus View Post
    yes i have different methods like comets_to_use.
    Which you call from the main thread once comets_to_use is done?

    Quote Originally Posted by Lumbricus View Post
    Qt Code:
    1. emit active_threads[i]->quit();
    To copy to clipboard, switch view to plain text mode 
    Well, quit() isn't a signal and if ti where you shouldn't emit another object's signals, but ok, that makes the thread's event loop stop, so the run() will return once the worker doesn't execute any slot anymore.


    Quote Originally Posted by Lumbricus View Post
    it didn't seem to work would that be a better approach?
    That at least makes you call terminate on the right thread.
    Not that you would ever want to call terminate() of course.

    Cheers,
    _

  10. #9
    Join Date
    Oct 2015
    Posts
    33
    Thanks
    14
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Shutting down threads prematurely

    My bad cut the post to short, i will try to reexplain:

    I make my worker object and create a thread, then move the object to the thread and start the thread.

    the started signal of the thread is connected to the slot of the worker i want to run e.g (comets_to_use() ).

    the worker contains a slot called on_shut_down_threads(). inside that i was using QThread::currentThread() to access the thread that was executing the worker. So i press a button and that emits a signal with is connected to this worker slot.

    So this worker is in the worker thread:

    Qt Code:
    1. void Worker:on_shut_down_threads()
    2. {
    3. QThread::currentThread()->exit();
    4. }
    To copy to clipboard, switch view to plain text mode 

    Since i want to close down the calculations in the slot comets_to_use() before it has finished I'm trying to find a way shut down that thread/or stop executing that worker slot.

    yes emitting the signal ->quit() was dumb.

    i still dont see why my thread does not close if i run

    Qt Code:
    1. active_threads[i]->terminate();
    To copy to clipboard, switch view to plain text mode 
    or:
    Qt Code:
    1. active_threads[i]->exit();
    To copy to clipboard, switch view to plain text mode 

    from the main thread thow?

  11. #10
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Shutting down threads prematurely

    Quote Originally Posted by Lumbricus View Post
    the worker contains a slot called on_shut_down_threads(). inside that i was using QThread::currentThread() to access the thread that was executing the worker.
    QThread::currentThread() returns the current thread.
    If that is in the slot called by the main thread, then the main thread is the current thread.

    Quote Originally Posted by Lumbricus View Post
    So i press a button and that emits a signal with is connected to this worker slot.
    So it depends on how the connection() was created.
    In an AutoConnection the receiver object's thread executes the slot, in a QueuedConnection the signal emitting thread executes the slot.

    So if you have a QueuedConnection as you claim, then accessing the current thread will never access the worker thread as it is not the current thread.

    i still dont see why my thread does not close if i run

    Quote Originally Posted by Lumbricus View Post
    Qt Code:
    1. active_threads[i]->terminate();
    To copy to clipboard, switch view to plain text mode 
    or:
    Qt Code:
    1. active_threads[i]->exit();
    To copy to clipboard, switch view to plain text mode 
    QThread::exit() is basically the same as QThread::quit(), both make the thread's event loop end.

    Lets go back to your need to that kind of threading approach.
    Aside from the slot that is run on start, what other slots does the worker have and how does the main thread trigger them?

    Cheers,
    _

  12. #11
    Join Date
    Oct 2015
    Posts
    33
    Thanks
    14
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Shutting down threads prematurely

    okai back to basics:

    Qt Code:
    1. for (int id=1;id<=guidata.numbers_of_workerthreads;id++)
    2. {
    3.  
    4. QThread *thread = new QThread;
    5.  
    6. Worker *worker = new Worker(&guidata,ui,id,&m_c,&mutex_file,&mutex_count);
    7.  
    8. worker->moveToThread(thread);
    9.  
    10. //connect events from worker<-> threads
    11. connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
    12. connect(thread, SIGNAL(started()), worker, SLOT(comets_to_use())); // when i start the thread it automaticly runs my slot that i specify
    13. connect(this, SIGNAL(shut_down_threads()), worker ,SLOT(on_shut_down_threads()));
    14. connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    15. connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    16. connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    17.  
    18. thread->start();
    19. }
    20. }
    To copy to clipboard, switch view to plain text mode 

    this is how i start a specific method in the worker other methods like my calc_stream_allcomets() ... would get exchanged with comets_to_use(); Depending on what button is clicked on the gui the worker slot that is executed on start is varied.

    As i said the calculations can be up to 1-2 days and sometimes i want to shut down the threads earlier e.g when you notice you made an input mistake of somekind.

  13. #12
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Shutting down threads prematurely

    Ok, so depending on what you want to do you have a different slot of the worker connected to the thread's started() signal, but in all cases one worker object is only ever used for one operation and either cancelled or fully executed and then discarded.

    Ok, then comets_to_use() and any of the other operations that need to be interruptible need check whether they need to stop.
    And the slot connected to shut_down_threads() needs to be connected with a DirectConnection and needs to change whatever the worker does to check for stopping.

    One option would be to check the worker's thread isInterruptionRequested() and use the worker's thread requestInterrruption() to switch to stopping.
    The worker would then also make the thread quit its event loop right before it exits the processing function.

    Cheers,
    _

  14. #13
    Join Date
    Oct 2015
    Posts
    33
    Thanks
    14
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Shutting down threads prematurely

    That sounds like a good approach to me. I'm still unclear how i would stop the worker from doing what it is doing to check if an interruption is wanted.

    What do I put in the worker slot that is connected? How would I change the worker from "working on my stuff". This is the Worker slot that is connected by direct connection to the main thread.

    Qt Code:
    1. void Worker::on_shut_down_threads()
    2. {
    3. if("workerthread_pointer?"->isInterruptionRequested())
    4. {
    5. ??
    6. }
    7.  
    8. }
    To copy to clipboard, switch view to plain text mode 

    Am i Understanding u right? I think a little pseudo code or code would help me understand

  15. #14
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Shutting down threads prematurely

    No, in that slot you request the interruption.
    Qt Code:
    1. void Worker::on_shut_down_threads()
    2. {
    3. thread()->requestedInterruption();
    4. }
    To copy to clipboard, switch view to plain text mode 

    The method that does the long calculation needs regularily to check for interruption.

    Cheers,
    _

  16. #15
    Join Date
    Oct 2015
    Posts
    33
    Thanks
    14
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Shutting down threads prematurely

    Okai anda,

    i think i've nearly understood, thx for your patience!

    In my worker slot i now have a check that is run through every 2sek. It checks if there is an interruption request from the main thread. The interrupt request is passed through with a direct connection. This is working at the moment. so in this part of the code how do i shut down the thread?


    this is in the executing worker slot (comets_to_use()) in the worker thread:

    Qt Code:
    1. //...worker doing stuff...
    2.  
    3. //comes past here every 2 sek
    4.  
    5. if (interruptRequested)
    6. {
    7. how do i shut down the thread from here?
    8. }
    To copy to clipboard, switch view to plain text mode 

    the only way i got it to work was to put this request at the beginning of all my nested loops and break; out of them so i quickly reach the end of the slot. then the thread processes my finished() signal and destructs normaly. is there a nicer way to do this?

  17. #16
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Shutting down threads prematurely

    You can nest the calls

    Qt Code:
    1. void Worker::comets_to_use()
    2. {
    3. comets_to_use_internal();
    4. thread()->quit();
    5. }
    To copy to clipboard, switch view to plain text mode 
    That way you can just return from comets_in_use_internal() whenever you want to end.

    Cheers,
    _

Similar Threads

  1. Qt Threads vs Native Threads performance
    By StackOverflow in forum Qt Programming
    Replies: 1
    Last Post: 14th November 2010, 13:14
  2. whatś the better in Threads
    By Tio in forum Newbie
    Replies: 15
    Last Post: 27th May 2010, 14:14
  3. Threads in Qt
    By freekill in forum Qt Programming
    Replies: 4
    Last Post: 11th November 2009, 19:49
  4. Qt threads
    By ^Nisok^ in forum Newbie
    Replies: 12
    Last Post: 22nd April 2009, 15:35
  5. shutting down as user
    By safknw in forum Qt Programming
    Replies: 6
    Last Post: 27th November 2006, 10:28

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.