Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qthread - trouble shutting down threads

Tags:

qthread

For the last few days, I've been trying out the new preferred approach for using QThreads without subclassing QThread. The trouble I'm having is when I try to shutdown a set of threads that I created. I regularly get a "Destroyed while thread is still running" message (if I'm running in Debug mode, I also get a Segmentation Fault dialog). My code is very simple, and I've tried to follow the examples that I've been able to find on the internet.

My basic setup is as follows: I've a simple class that I want to run in a separate thread; in fact, I want to run 5 instances of this class, each in a separate thread. I have a simple dialog with a button to start each thread, and a button to stop each thread (10 buttons). When I click one of the "start" buttons, a new instance of the test class is created, a new QThread is created, a movetothread is called to get the test class object to the thread...also, since I have a couple of other members in the test class that need to move to the thread, I call movetothread a few additional times with these other items. Note that one of these items is a QUdpSocket, and although this may not make sense, I wanted to make sure that sockets could be moved to a separate thread in this fashion...I haven't tested the use of the socket in the thread at this point.

Starting of the threads all seem to work fine. When I use the linux top command to see if the threads are created and running, they show up as expected.

The problem occurs when I begin stopping the threads. I randomly (or it appears to be random) get the error described above.

Class that is to run in separate thread:

// Declaration
class TestClass : public QObject
{
Q_OBJECT
public:
explicit TestClass(QObject *parent = 0);
QTimer m_workTimer;
QUdpSocket m_socket;

Q_SIGNALS:
void finished();

public Q_SLOTS:
void start();
void stop();
void doWork();

};

// Implementation
TestClass::TestClass(QObject *parent) :
QObject(parent)
{

}

void TestClass::start()
{
  connect(&m_workTimer, SIGNAL(timeout()),this,SLOT(doWork()));
  m_workTimer.start(50);
}

void TestClass::stop()
{
  m_workTimer.stop();
  emit finished();
}

void TestClass::doWork()
{
int j;
for(int i = 0; i<10000; i++)
  {
    j = i;
  }
}

Inside my main app, code called to start the first thread (similar code exists for each of the other threads):

mp_thread1 = new QThread();
mp_testClass1 = new TestClass();
mp_testClass1->moveToThread(mp_thread1);
mp_testClass1->m_socket.moveToThread(mp_thread1);
mp_testClass1->m_workTimer.moveToThread(mp_thread1);

connect(mp_thread1, SIGNAL(started()), mp_testClass1, SLOT(start()));
connect(mp_testClass1, SIGNAL(finished()), mp_thread1, SLOT(quit()));
connect(mp_testClass1, SIGNAL(finished()), mp_testClass1, SLOT(deleteLater()));
connect(mp_testClass1, SIGNAL(finished()), mp_thread1, SLOT(deleteLater()));
connect(this,SIGNAL(stop1()),mp_testClass1,SLOT(stop()));

mp_thread1->start();

Also inside my main app, this code is called when a stop button is clicked for a specific thread (in this case thread 1):

emit stop1();

Sometimes it appears that threads are stopped and destroyed without issue. Other times, I get the error described above.

Any guidance would be greatly appreciated.

Thanks,

Bryan

like image 573
Bryan Greenway Avatar asked Apr 08 '26 08:04

Bryan Greenway


1 Answers

http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

"Finally, to prevent nasty crashes because the thread hasn’t fully shut down yet when it is deleted, we connect the finished() of the thread (not the worker!) to its own deleteLater() slot. This will cause the thread to be deleted only after it has fully shut down."

Please try replacing:

    connect(mp_testClass1, SIGNAL(finished()), mp_thread1, SLOT(deleteLater()));

with:

    connect(mp_thread1, SIGNAL(finished()), mp_thread1, SLOT(deleteLater()));
like image 126
Nemo Avatar answered Apr 30 '26 01:04

Nemo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!