Evgenii Legotckoi
Evgenii LegotckoiMay 15, 2016, 5:11 p.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.

Do you like it? Share on social networks!

  • July 10, 2017, 9:02 p.m.

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

Evgenii Legotckoi
  • July 10, 2017, 9:34 p.m.

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

  • Aug. 7, 2017, 3:12 p.m.

Взял Ваш пример для 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 и плюсах

Evgenii Legotckoi
  • Aug. 7, 2017, 3:30 p.m.

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

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

Форум здесь .
  • Aug. 7, 2017, 4:48 p.m.

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

Evgenii Legotckoi
  • Aug. 7, 2017, 6:37 p.m.

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

  • Aug. 15, 2017, 7:49 p.m.

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

Evgenii Legotckoi
  • Aug. 15, 2017, 8:32 p.m.

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

  • Sept. 4, 2017, 8:57 p.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() по умолчанию.
Evgenii Legotckoi
  • Sept. 5, 2017, 12:31 a.m.

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

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

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

В том и дело что хотел без мютексов обойтись. т.е. суть проблемы есть старая программа, рабочая и три потока в ней  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
Evgenii Legotckoi
  • Sept. 5, 2017, 12:27 p.m.

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

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

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

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

Evgenii Legotckoi
  • June 12, 2018, 12:42 p.m.

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

  • March 16, 2021, 11:07 p.m.

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

Evgenii Legotckoi
  • July 2, 2021, 4:35 p.m.

connect(&thread01, &QThread::started, Server, &myserver::run);

  • Feb. 28, 2023, 3:26 p.m.
  • (edited)

Ввожу 1 в Write 1, ввожу 2 в Write 2, нажимаю Start и сразу Stop. Сначала вижу очень много одинаковых строк, а потом сообщение об ошибке. При этом программа не крашится, но предупреждение настораживает... Почему так? Неужели надо &QThread::terminate заменить на &QThread::quit ? Вот что у меня вышло после. Варнинг перестал сыпаться...
Ubuntu 22, Qt 6.

"1" "" 212463
"2" "1" 253535
"1" "" 212464
"1" "" 212465
"2" "1" 253536
"2" "1" 253537
Qt has caught an exception thrown from an event handler. Throwing
exceptions from an event handler is not supported in Qt.
You must not let any exception whatsoever propagate through Qt code.
Qt has caught an exception thrown from an event handler. Throwing
exceptions from an event handler is not supported in Qt.
You must not let any exception whatsoever propagate through Qt code.

ThreadLessonTwo problem

Evgenii Legotckoi
  • March 13, 2023, 6:08 p.m.

Вообще, правильнее использоать quit, поскольку terminate - это более жёсткий вариант, на тот случай, если поток схватил deadlock.
Так что в итоге вы правильно всё исправили. Статья старая, на тот момент я делал больше глупых ошибок :-)


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

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

  • Result:60points,
  • Rating points-1

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

  • Result:50points,
  • Rating points-4

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

  • Result:73points,
  • Rating points1
Last comments
JonnyJoMarch 30, 2023, 9:57 p.m.
Qt/C++ - Lesson 021. The drawing mouse in Qt Евгений, здравствуйте! Только начал изучение Qt и возник вопрос по 21ому уроку. После написания кода, выдаёт следующие ошибки В чём может быть проблема?
Алексей НиколаевMarch 26, 2023, 7:10 p.m.
Qt/C++ - Lesson 042. PopUp notification in the Gnome style using Qt Добрый день, взял за основу ваш PopUp notification , и немного доработал его под свои нужды. Добавил в отдельном eventloop'e всплывающую очередь уведомлений с анимацией и таймеро…
Алексей НиколаевMarch 26, 2023, 7:04 p.m.
Qt/C++ - Lesson 042. PopUp notification in the Gnome style using Qt Включите прозрачность в композит менеджере fly-admin-theme : fly-admin-theme ->Эффекты и всё заработает.
NSProjectMarch 25, 2023, 12:35 a.m.
Django - Lesson 062. How to write a block-template tabbar tag like the blocktranslate tag Да не я так к примеру просто написал.
Evgenii Legotckoi
Evgenii LegotckoiMarch 24, 2023, 8:09 p.m.
Django - Lesson 062. How to write a block-template tabbar tag like the blocktranslate tag Почитайте эту статью про "хлебные крошки"
Now discuss on the forum
BlinCTApril 1, 2023, 3:16 p.m.
Нужен совет по работе с ListView и несколькими моделями Спасибо, сейчас займусь этим.
NSProjectMarch 31, 2023, 12:55 p.m.
Проверка комментария принадлежит он пользователю или нет DRF (Django Rest Framework) Здравствуйте! Сегодня я столкнулся с такой проблеммой. Существует модель комметариев. Где их соответственно достаточное количество. Все они выводятся при помощи запроса ajax (axios). Так ка…
PisychMarch 30, 2023, 12:50 p.m.
Как подсчитать количество по условию? Да! Вот так работает! Огромное Вам спасибо! ........
Evgenii Legotckoi
Evgenii LegotckoiMarch 29, 2023, 2:11 p.m.
Замена поля ManyToMany Картинки точно нужно хранить в медиа директории на сервере, а для обращения использовать ImageField. Который будет хранить только путь к изображению на сервере. Хранить изображения в базе данных…
Виталий АнисимовJan. 30, 2023, 2:17 a.m.
Как добавить виртуальную клавиатура с Т9 в своей проект на QML. Добрый день. Прошу помочь, пишу небольше приложение в Qt. Добвил в свой проект виртуальную клавиатуру от Qt. Но как добавить в него возможность изменения Т9 никак не могу понять.

Follow us in social networks