Safe Thread Management in Qt Applications
Thread Termination Methods in QThread
Unsafe Termination
- QThread::terminate()
- Immediately stops thread execution (implementation-dependent)
- Dangerous: Terminates without cleanup, may leave resources locked
- Requires QThread::wait() after calling
- Disabled termination delays until re-enabled via setTerminationEnabled()
- Not recommended for production use
Proper Termination Methods
-
QThread::exit(int returnCode = 0)
- Gracefully exits the thread's event loop
- Returns specified status code (0 for success)
- Only affects event processing, not immediate thread termination
-
QThread::quit()
- Equivalent to exit(0)
- No effect if thread lacks an event loop
Safe Thread Shutdown Pattern
Common crash scenario: Destroyed while thread is still running occurs when resources are released before thread completion. Avoid these unsafe patterns:
// Unsafe examples
thread->quit();
delete thread;
// OR
thread->terminate();
delete thread;
Recommended approach:
- Connect QThread::finished to deleteLater for automatic cleanup
- Explicitly quit the thread
- Optionally wait for completion
Implementation Example
Thread Initialization:
Worker* worker = new Worker;
QThread* thread = new QThread;
worker->moveToThread(thread);
// Automatic cleanup connections
connect(thread, &QThread::finished, worker, &Worker::deleteLater);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
thread->start();
Thread Termination:
thread->quit(); // or thread->exit(0)
thread->wait(); // Blocks until thread completes
worker = nullptr;
thread = nullptr;
moveToThread Implementation Pattern
- Create Worker class inheriting QObject with work method
- Manager class creates QThread and Worker instances
- Move worker to thread's event loop
- Connect signals/slots for work execution
Header Example:
class Worker : public QObject {
Q_OBJECT
public:
explicit Worker(QObject* parent = nullptr);
void executeTask();
signals:
void taskCompleted();
};
class Manager : public QObject {
Q_OBJECT
public:
explicit Manager(QObject* parent = nullptr);
~Manager();
signals:
void startTask();
private slots:
void handleCompletion();
private:
QThread* workerThread;
Worker* taskWorker;
};