Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing Multithreading in Qt with moveToThread and Synchronization

Tech 1

Using moveToThread for Worker Threads

This approach invovles moving a worker object to a dedicated thread, enabling background task execution. Synchronization is achieved using QMutex and QWaitCondition, particularly when the worker thread suspends itself and awaits a signal from the main thread.

Header File: TaskProcessor.h

#ifndef TASKPROCESSOR_H
#define TASKPROCESSOR_H

#include <QObject>
#include <QMutex>
#include <QWaitCondition>

class TaskProcessor : public QObject
{
    Q_OBJECT

public:
    explicit TaskProcessor(QObject* parent = nullptr);

public slots:
    void executeTask();
    void resumeTask();

signals:
    void taskResumed();
    void taskInitiated();

private slots:
    void handleResume();
    void handleInitiation();

private:
    QMutex lock;
    QWaitCondition pauseCondition;
};

#endif // TASKPROCESSOR_H

Implementation File: TaskProcessor.cpp

#include "TaskProcessor.h"
#include <QDebug>
#include <QThread>

TaskProcessor::TaskProcessor(QObject *parent)
    : QObject{parent}
{
    connect(this, &TaskProcessor::taskInitiated, this, &TaskProcessor::handleInitiation);
    connect(this, &TaskProcessor::taskResumed, this, &TaskProcessor::handleResume);
}

void TaskProcessor::executeTask()
{
    qDebug() << QThread::currentThreadId() << "Executing task";
    emit taskInitiated();
}

void TaskProcessor::resumeTask()
{
    qDebug() << QThread::currentThreadId() << "Resuming task";
    qDebug() << QThread::currentThreadId() << "Signaling condition";
    pauseCondition.wakeAll();
}

void TaskProcessor::handleResume()
{
    qDebug() << QThread::currentThreadId() << "Resume handled";
}

void TaskProcessor::handleInitiation()
{
    qDebug() << QThread::currentThreadId() << "Initiation handled";
    int counter = 0;
    while (true)
    {
        lock.lock();
        qDebug() << QThread::currentThreadId() << "Iteration" << counter;
        QThread::sleep(1);
        ++counter;

        if (counter % 5 == 0)
        {
            qDebug() << QThread::currentThreadId() << "Waiting at" << counter;
            pauseCondition.wait(&lock);
        }
        lock.unlock();
    }
}

Header File: Manager.h

#ifndef MANAGER_H
#define MANAGER_H

#include <QObject>

class TaskProcessor;

class Manager : public QObject
{
    Q_OBJECT

public:
    explicit Manager(QObject* parent = nullptr);
    ~Manager();

public slots:
    Q_INVOKABLE void startTask();
    Q_INVOKABLE void suspendTask();
    Q_INVOKABLE void continueTask();
    Q_INVOKABLE void validate();

private:
    QThread* workerThread;
    TaskProcessor* processor;
};

#endif // MANAGER_H

Implementation File: Manager.cpp

#include "Manager.h"
#include <QDebug>
#include <QThread>
#include "TaskProcessor.h"

Manager::Manager(QObject *parent)
    : QObject{parent}
{
    qDebug() << "Manager initialized";
    workerThread = new QThread;
    processor = new TaskProcessor;
    processor->moveToThread(workerThread);
    workerThread->start();
}

Manager::~Manager()
{
    qDebug() << QThread::currentThreadId() << "Manager cleanup";
    workerThread->terminate();
    if (workerThread->wait())
    {
        delete processor;
        delete workerThread;
    }
    qDebug() << QThread::currentThreadId() << "Cleanup complete";
}

void Manager::startTask()
{
    qDebug() << QThread::currentThreadId() << "Starting task";
    processor->executeTask();
}

void Manager::suspendTask()
{
    qDebug() << QThread::currentThreadId() << "Suspending task";
    // Suspension logic placeholder
}

void Manager::continueTask()
{
    qDebug() << QThread::currentThreadId() << "Continuing task";
    processor->resumeTask();
}

void Manager::validate()
{
    qDebug() << QThread::currentThreadId() << "Validation call";
}

QWaitCondition Methods

wakeAll

This method awakens all threads waiting on the condition. The order of awakening depends on the operating system's scheduling and cannot be predetermined.

wakeOne

This method awakens a single thread waiting on the condition. The specific thread awakened is determined by the OS scheduler. To target a particular thread, use separate wait conditions for different threads.

References

  • QThread Class | Qt Core 5.15.15
  • QThreadPool Class | Qt Core 5.15.15
  • Synchronizing Threads | Qt 5.15
  • QWaitCondition Class | Qt Core 5.15.15
  • Wait Conditions Example | Qt Core 5.15.15

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.