Evgenij LegotskojMay 15, 2016, 6:11 a.m.

Qt/C++ - Lesson 048. QThread — How to work with threads using moveToThread

In a previous article we are only a little touch to working with threads , and in the version that is more for the customization of thread, although it can be used to perform outside work not directly related to the thread. That is an option with inheritance from QThread and override the method run().

Now we will create ExampleObject class whose objects will be transferred to the individual threads via moveToThread() method and implemented in most of these flows. A useful work will make the slot method run() , which will be defined in this class. What is important, object class will inherit from QObject .

In order to work in the run() method can be performed in cycles, using a while loop, which will operate using variable bool m_running. For the convenience of working with this variable we define it as Q_PROPERTY . But at the end of the work will emit finished() signal.

Work algorithm

  1. Create an QThread object and the ExampleObject class object;
  2. Connect the signal QThread::started() method to ExampleObject::run() ;
  3. Connect the signal ExampleObject::finished() to slot QThread::terminate() , so that on completion of useful work to complete the flow;
  4. Set m_running variable to true, to allow the work cycle, or else this method once completed;
  5. Run stream using the method start() ;
  6. When it is necessary to complete useful work object, set the variable in m_running to false. Running run() method and the flux in which he lives the object will be completed automatically and correctly.

Project structure and appearance of the application

  • ThreadLessonTwo.pro - the profile of the project;
  • exampleobject.h - header of the object file to be transmitted in a thread;
  • exampleobject.cpp - file source object that will be passed in the thread;
  • mainwindow.h - header file of the main application window;
  • mainwindow.cpp - file source code of the main application window;
  • mainwindow.ui - file forms the main application window;
  • main.cpp - the file source code to the main function.

Attached are two objects to be determined, and the two streams. With the help of the application interface, we will show some information in the output qDebug() , and will start and stop the thread.


To begin, consider the contents of the object header file. In this file, three properties announced Q_PROPERTY :

  1. running - it is a variable, by means of which will be implemented in the control cycle a run() method and, accordingly, will affect the completion of the useful work of the object.
  2. message - a string that will be sent to output in qDebug() from the main application window
  3. message_2 - this is the second line, which will also be displayed in qDebug() , but will also be used for transmission of the second stream.

#include <QObject>

class ExampleObject : public QObject
    // A property that controls the work of thread
    Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged)
    // The first message in the object
    Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
    // The second message that will be transmitted via a signal/slot to the second object
    Q_PROPERTY(QString message_2 READ message_2 WRITE setMessage_2 NOTIFY message_2Changed)

    bool m_running;
    QString m_message;
    QString m_message_2;
    int count;  

    explicit ExampleObject(QObject *parent = 0);
    bool running() const;
    QString message() const;
    QString message_2() const;

    void finished();    // The signal, in which we will complete the thread after the end of the run method
    void runningChanged(bool running);
    void messageChanged(QString message);
    void message_2Changed(QString message_2);
    void sendMessage(QString message);

public slots:
    void run(); // Method with payload which can be carried out in a loop
    void setRunning(bool running);
    void setMessage(QString message);
    void setMessage_2(QString message_2);



All our interest is reduced to the method run() , in which the while loop will increment the counter count and the information will be displayed with the message m_message , m_message_2 and this counter as long as the variable m_running not be exposed to a value of false. At the exit of the loop at the end of execution run() method will be released finished() signal, in which the flow is completed, which will be the object.

#include "exampleobject.h"
#include <QDebug>

ExampleObject::ExampleObject(QObject *parent) :


bool ExampleObject::running() const
    return m_running;

QString ExampleObject::message() const
    return m_message;

QString ExampleObject::message_2() const
    return m_message_2;

// The most important method, which will be carried out "useful" work object
void ExampleObject::run()
    count = 0;
    // Variable m_running responsible for the object in the stream.
    // If false, the work is completed
    while (m_running)
        emit sendMessage(m_message); 
        qDebug() << m_message << " " << m_message_2 << " " << count;
    emit finished();

void ExampleObject::setRunning(bool running)
    if (m_running == running)

    m_running = running;
    emit runningChanged(running);

void ExampleObject::setMessage(QString message)
    if (m_message == message)

    m_message = message;
    emit messageChanged(message);

void ExampleObject::setMessage_2(QString message_2)
    if (m_message_2 == message_2)

    m_message_2 = message_2;
    emit message_2Changed(message_2);


The header of the main window of the application declared slots for processing keystrokes to record messages to the objects that will be carried out in the streams, as well as slots for starting and stopping the flow. In addition, we declare two objects ExampleObject class and two objects of QThread class.


#include <QMainWindow>
#include <QThread>
#include "exampleobject.h"

namespace Ui {
class MainWindow;

class MainWindow : public QMainWindow

    explicit MainWindow(QWidget *parent = 0);

private slots:
    void on_write_1_clicked();  // Slot for writind data from lineEdit_1 to the first object in the first stream
    void on_write_2_clicked();  // Slot for writind data from lineEdit_1 to the second object in the first stream
    void on_start_clicked();   
    void on_stop_clicked();     

    Ui::MainWindow *ui;
    QThread thread_1;       
    QThread thread_2;       
    ExampleObject exampleObject_1;  
    ExampleObject exampleObject_2; 

#endif // MAINWINDOW_H


And now combine all of the previous code in a working application in the source code of the main program window. In the constructor of the class, as has been said in the beginning, you need to connect signals started() of the threads to the slots run() our test objects, and signals the finished(), to the slots terminate() of threads to complete the work streams at completion method run().

Also joined sending message signal exampleObject_1 object to slot installation exampleObject_2 messages. But that information can be transmitted, you need the fifth argument in the connect method to transfer the flag Qt :: DirectConnection, which would establish a direct connection of objects and allows to transmit information through a system of signals and slots .

And for the transfer of objects in the threads necessary to use the method moveToTrhead().

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    ui(new Ui::MainWindow)

    connect(&thread_1, &QThread::started, &exampleObject_1, &ExampleObject::run);
    connect(&thread_2, &QThread::started, &exampleObject_2, &ExampleObject::run);

    connect(&exampleObject_1, &ExampleObject::finished, &thread_1, &QThread::terminate);
    connect(&exampleObject_2, &ExampleObject::finished, &thread_2, &QThread::terminate);

    connect(&exampleObject_1, &ExampleObject::sendMessage, &exampleObject_2, &ExampleObject::setMessage_2, Qt::DirectConnection);

    delete ui;

void MainWindow::on_write_1_clicked()

void MainWindow::on_write_2_clicked()

void MainWindow::on_start_clicked()

void MainWindow::on_stop_clicked()


As a result, the application can be obtained following the following conclusion qDebug(), which shows the parallel operation of facilities in the streams, as well as the transfer of information from one thread to another.

"thread 1"   ""   11422
"thread 2"   "thread 1"   11446
"thread 1"   ""   11423
"thread 2"   "thread 1"   11447
"thread 1"   ""   11424
"thread 2"   "thread 1"   11448
"thread 1"   ""   11425
"thread 2"   "thread 1"   11449
"thread 1"   ""   11426
"thread 2"   "thread 1"   11450
"thread 1"   ""   11427
"thread 2"   "thread 1"   11451

Download the project can be on the following link: Thread Lesson Two


We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate

У меня происходит переполнение счетчика count, появляется ошибка malloc(): memory corruption (fast). Не подскажите, как с этим бороться?

А что делали? Повторяете урок или как? Пытались просто скачать проект в конце статьи и запустить?


Взял Ваш пример для Qt4.8 (не спрашивайте почему). переписал связь сигнал/слот след. образом:

    // Запуск выполнения метода run будет осуществляться по сигналу запуска от соответствующего потока
    QObject::connect(&thread_1,        SIGNAL(started()),
                     &exampleObject_1, SLOT(run()));
    QObject::connect(&thread_2,        SIGNAL(started()),
                     &exampleObject_2, SLOT(run()));
    //connect(&thread_1, &QThread::started, &exampleObject_1, &ExampleObject::run);
    //connect(&thread_2, &QThread::started, &exampleObject_2, &ExampleObject::run);
    // Остановка потока же будет выполняться по сигналу finished от соответствующего объекта в потоке

    QObject::connect(&exampleObject_1,        SIGNAL(finished()),
                     &thread_1, SLOT(terminate()));
    QObject::connect(&exampleObject_2,        SIGNAL(finished()),
                     &thread_2, SLOT(terminate()));
    //connect(&exampleObject_1, &ExampleObject::finished, &thread_1, &QThread::terminate);
    //connect(&exampleObject_2, &ExampleObject::finished, &thread_2, &QThread::terminate);
    // коннект для передачи данных из первого объекта в первом потоке, ко второму объекту во втором потоке
    QObject::connect(&exampleObject_1,        SIGNAL(sendMessage(QString)),
                     &exampleObject_2,        SLOT(setMessage_2(QString)));
    //connect(&exampleObject_1, &ExampleObject::sendMessage,
    //        &exampleObject_2, &ExampleObject::setMessage_2, Qt::DirectConnection);

В итоге получаю

"thread 1" "" 1752

"thread 2" "" 1747

"thread 1" "" 1753

"thread 2" "" 1748

"thread 1" "" 1754

т.е. связь между потоками не работает.

Вижу еще волшебное слово Qt::DirectConnection, пробовал добавить - нет результата

Добавил  еще в pro файл запись CONFIG += no_keywords - тоже не помогло

Что подскажите

PS: я нубер в Qt и плюсах

Не вижу всего кода, по этому куску кода невозможно сказать, в чём ошибка. На первый взгляд код написан верно.

P/S/ Если соберетёсь кидать весь код, то создавайте тогда новую тему на форуме. Там есть возможность прикрепить архив с проектом к теме и сообщениям. В комментариях под статьёй не стоит постить большие куски кода.

Форум здесь .

В остальном код как и Вашем примере

Тогда мне больше нечего Вам сказать. Давно уже не работал с Qt 4.8 и приниципиально не работаю с ним сейчас.

  • #
  • Aug. 15, 2017, 8:49 a.m.

В qt5.6 всё нормально заработало. С 4.8 - нет

Нууу... тут уже вопрос к самому Qt4.8. Если честно, идей нет, да и копаться в deprecated коде желания тоже нет.

  • #
  • Sept. 4, 2017, 9:57 a.m.

В моем коде с двумя потоками и выводом сообщений в textEdit при использовании Qt::DirectConnection падает в "The program has unexpectedly finished" через 10-20 сообщений.  При использовании Qt::QueuedConnection, работает.

Все же как правильно использовать ?
Нашел на другом форуме:
  • Qt::DirectConnection — сигнал обрабатывается сразу вызовом соответствующего метода слота
  • Qt::QueuedConnection — сигнал преобразуется в событие и ставится в общую очередь для обработки
  • Qt::AutoConnection — это автоматический режим, который действует следующим образом: если отсылающий сигнал объект находится в одном потоке с принимающим его объектом, то устанавливается режим Qt::DirectConnection , в противном случае — режим Qt::QueuedConnection . Этот режим ( Qt::AutoConnection ) определен в методе connection() по умолчанию.

В принципе все варианты возможны, зависит от ситуации.
Наиболее правильным по максимому использовать Qt::AutoConnection. Если что-то по какой-то причине не работает, то разбираться в чём причина и возможно переходить на Qt::DirectConnection , при данном методе слот будет вызываться сразу же, юез постановки в очередь событий. Иногда может потребоваться, чтобы дать приоритет вызову слота. Ведь слоты вызываются в той последовательности, как они был подключены в коде.
Тут уже возникает вопрос в потокобезопасности. Поэтому сложный код следует блокировать мьютексами.Теми же самыми QMutexLocker и QMutex, например,

int complexFunction(int flag)
    QMutexLocker locker(&mutex);

    // ToDo something
    return retVal;
В данном случае mutex является объектов класса QMutex, который объявлен в заголовке класса. Можете проверить у себя работу вашего класса с использование QMutex и Qt::DirectConnection .

В том и дело что хотел без мютексов обойтись. т.е. суть проблемы есть старая программа, рабочая и три потока в ней  A-B-(C1...Cn) .

A - поток основной программы;
B - поток для QModbusTcpServer;
С1...Cn - потоки опроса приборов по протоколу xxx [RTU];

Задача передать из потоков собранные данные потоков C1...Cn в один JSON контейнер и отправить в QWebSocketServer.
В QWebSocketServer создал слот (для отладки и в MainWindow) привязал сигналы из C1...Cn,  передаю простой тип QString.

Вопрос , на ваш взгляд потокобезопасно так делать или нет ? Ну и как писал Qt::DirectConnection вызывает глюк, без него работает.
P.S. Qt 5.6.1

Я глубоко в дебри многопоточности не зарывался, но если разбираться с нюансами и поднять в памяти то, что мне говорили более опытные коллеги. То можно сделать следующие выводы:

  • Qt::QueuedConnection является потокобезопасным вариантом и информация не портится при передаче данных потому, что все сигналы отправляют информацию в очередь сообщений и информация обрабатывается поочерёдно. Это актуально для передачи информации между несколькими потоками.
  • Qt::DirectConnection используется тогда, когда и отправитель сигнала и получатель находятся в одном потоке, поскольку такая передача информации будет потокобезопасной. Всё равно другой код не начнёт работу с текущим слотом, пока слот не завершится. Но это не значит, что такое соединение нельзя использовать при передачи информации между потоками. Только в данном случае нужно обезопаситься мьютексами. Тем более, что их реализация позволяет это делать в одну строку в методе.
Поэтому у вас всё заработало с Qt::QueuedConnection и сломалось с Qt::DirectConnection, очевидно потоки конкурировали друг с другом и получилось, что была испорчена память.

Поэтому в вашем случае работайте без Qt::DirectConnection , и подумайте над использованием мьютексов. Если начнёт падать и с Qt::QueuedConnection , то стоит подумать над подключением мьютексов.

Возможно таким же способом передать туда QTcpSocket?

Да, это должно работать. Главное при передаче данных в основные потоки защищайте данные от конкурентного доступа мьютексами.


Не получается сделать connect, получаю гору ошибок. В чем может быть дело ?


Only authorized users can post comments.
Please, Log in or Sign up

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting
  • Viktor
  • April 14, 2021, 3:40 p.m.

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:50points,
  • Rating points-4
  • Fedya
  • April 14, 2021, 4:04 a.m.

C++ - Test 001. The first program and data types

  • Result:66points,
  • Rating points-1

C++ - Тест 003. Условия и циклы

  • Result:71points,
  • Rating points1
Last comments

PyQt5 - Tutorial 009. Using QThread with MoveToThread

Hello. Let's say I want to send some variables to "run" define. How can we do that? I modified your code, I tried something like below, but the GUI is frozen that way. I could not be able to und…

Распознавание изображений на Python с помощью TensorFlow и Keras

почему то вместо 50000 обрабатывает по 782 картинки кажду. эпоху

Qt/C++ - Lesson 008. QDataWidgetMapper - Working with the database via a widget

Понял сам так - происходит через setTable() "Sets the database table on which the model operates to tableName. Does not select data from the table, but fetches its field information", а затем че…

Qt/C++ - Lesson 008. QDataWidgetMapper - Working with the database via a widget

Начал делать что-то похожее, но без sql. Не очень понимаю, что делает mapper->setCurrentModelIndex(model->index(row,0)); Вернее не понимаю вот что: откуда он берёт данные, кот…
Now discuss on the forum

Помогите переложить код QML OpenCV c PyQt5 на PySide2

Структура проекта ├── main.py ├── main.qml └── PyCVQML ................├── cvcapture.py ................├── cvitem.py ................└── init .py …

QScrollArea dynamically add QCheckBoxes

Всё правильно. Это просто спамер, который отправился в вечный бан.

Подключение приложения qt qml к БД postgresql из приложения qt qml c++, собранное под android

Алексей, код уже написан. Приложение работает под ОС Windows, но хочется его запустить на Android. По поводу сборки драйвера, не получается найти свежей инструкции, а главное рабочей.

Qt, Sqlite и Android. Как подключить базу данных?

Добрый день, добавил базу к ресурсам, приложение вроде как открывает БД, но данные не видет, что может быть не так? qt qml c++ под android m_db = QSqlDatabase::addDatabase("QSQLITE")…
  • BlinCT
  • April 13, 2021, 4:11 a.m.

Отображение талицы в Column в qml обьекте

Проблема в том что я все таблицы перевел на вторые контролы, все таблицы на них сделаны, шаблон для них всех создан. Только под 2 эти таблицы возвпащать все на первые контролы не думаю что прави…
© EVILEG 2015-2021
Recommend hosting TIMEWEB