Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.80/41: Рейтинг темы: голосов - 41, средняя оценка - 4.80
2 / 2 / 2
Регистрация: 27.02.2016
Сообщений: 247

Как сделать вторичный поток с постоянный жизненным циклом и управлением из главного потока

24.11.2019, 14:52. Показов 9222. Ответов 113
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Имеется объект, который живёт в другом потоке и выполняет различные задачи по запросам или выполняет повторяющиеся задачи.

Более приземленное описание. Через протокол modbus RTU опрашиваются датчики. Датчиков 247 штук. Используются 3 команды, чтение регистров, запись регистров, чтение ID. Управление датчиками может быть ручное или автоматическое. При ручном режиме принимаем данные из главного потока и передаем на датчик, после ответа датчика передаем данные в главный поток для записи в usb устройство и отображение на экране. При автоматическом режиме управляем датчиками по заданному алгоритму и отсылаем ответы датчиков в главный поток для записи на usb устройство и отображения данных.

Вот не знаю как лучше реализовать это.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
24.11.2019, 14:52
Ответы с готовыми решениями:

Как усыплять дочерний поток реализуя управление элементами из главного потока методом Invoke
как управлять элементами из главного потока в дочернем? Если напишите методом Invoke, то объясните тогда - как заставять в определённых...

Как запустить вторичный поток
Доброго дня, Помогите разобраться что не так, как это победить: срабатывает исключение InvalidOperationException в строчке...

VC++6.0, как из порожденного потока прочитать переменную главного потока?
Visual C++ 6.0 SP5 Простое диалоговое окно, (MFC) созданное мастером среды VC По нажатию на кнопку создаю поражденный поток, в...

113
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
25.11.2019, 10:27
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Алексей1153 Посмотреть сообщение
ничего плохого нет в этой практике
Т.е., многочисленные авторы (включая одного из разработчиков Qt) ошибаются, я вас правильно понимаю?)))
Да и по логике, смешивание кода запуска потока и пользовательского кода в одну кучу не очень хорошая идея. Куда как проще реализовать свой класс, а потом просто создать его, поместить в поток и пусть он там работает.
Хотя, каждый делает как он хочет. Мне удобнее именно так, как я сказал выше.
0
фрилансер
 Аватар для Алексей1153
6501 / 5734 / 1134
Регистрация: 11.10.2019
Сообщений: 15,355
25.11.2019, 10:32
insite2012, они не ошибаются, они ленятся объяснять ) Например, когда я наследую поток, я не собираюсь там использовать сигналы и слоты. Но если вдруг приспичило, можно свою петлю прикрутить
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
25.11.2019, 10:35
Цитата Сообщение от Алексей1153 Посмотреть сообщение
они не ошибаются, они ленятся объяснять
А вот и нет, в сети достаточно примеров, где очень подробно рассмотрены оба способа.
Кому как, но мне удобнее не мешать все в одну кучу, мой код в одном месте, без лишних телодвижений. Нужно-я запускаю его без потока (как правило, при отладке через консоль), нужно-в GUI уже отправляю его в поток. То есть мой код неизменен, и работает при любом его использовании.
0
2 / 2 / 2
Регистрация: 27.02.2016
Сообщений: 247
26.11.2019, 08:03  [ТС]
Сделал через moveToThread.

threadobjectbalancer.h
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#ifndef THREADOBJECTBALANCER_H
#define THREADOBJECTBALANCER_H
 
#include <QObject>
#include<QDebug>
 
class ThreadObjectBalancer : public QObject
{
    Q_OBJECT
 
    // Свойство, управляющее работой потока
    Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged)
    // Первое сообщение в объекте
    Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
    // Второе сообщение, которое будем передавать через сигнал/слот во второй объект
    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;  // Счётчик, по которому будем ориентироваться на то,
                // что потоки выполняются и работают
public:
    explicit ThreadObjectBalancer(QObject *parent = 0);
    bool running() const;
    QString message() const;
    QString message_2() const;
 
signals:
    void finished();    // Сигнал, по которому будем завершать поток, после завершения метода run
    void runningChanged(bool running);
    void messageChanged(QString message);
    void message_2Changed(QString message_2);
    void sendMessage(QString message);
 
public slots:
    void run(); // Метод с полезной нагрузкой, который может выполняться в цикле
    void setRunning(bool running);
    void setMessage(QString message);
    void setMessage_2(QString message_2);
};
 
#endif // THREADOBJECTBALANCER_H


threadobjectbalancer.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "threadobjectbalancer.h"
 
ThreadObjectBalancer::ThreadObjectBalancer(QObject *parent) :
    QObject(parent),
    m_message(""),
    m_message_2("")
{
 
}
 
 
bool ThreadObjectBalancer::running() const
{
    return m_running;
}
 
 
QString ThreadObjectBalancer::message() const
{
   return m_message;
}
 
 
QString ThreadObjectBalancer::message_2() const
{
    return m_message_2;
}
 
 
void ThreadObjectBalancer::run()
{
    count = 0;
 
    while (m_running)
    {
        count++;
      //  emit sendMessage(m_message); // Высылаем данные, которые будут передаваться в другой поток
        qDebug() << m_message << " " << m_message_2 << " " << count;
    }
    emit finished();
}
 
 
void ThreadObjectBalancer::setRunning(bool running)
{
    if (m_running == running)
        return;
 
    m_running = running;
    count = 0;
    emit runningChanged(running);
}
 
 
void ThreadObjectBalancer::setMessage(QString message)
{
    if (m_message == message)
        return;
 
    m_message = message;
    emit messageChanged(message);
}
 
 
void ThreadObjectBalancer::setMessage_2(QString message_2)
{
    if (m_message_2 == message_2)
        return;
 
    m_message_2 = message_2;
    emit message_2Changed(message_2);
}


mainwindow.h
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include <QTimer>
#include <QTime>
#include <QDate>
#include <QPainter>
#include <QKeyEvent>
#include <mythreadbalancer.h>
#include <threadobjectbalancer.h>
#include <QThread>
 
namespace Ui {
class MainWindow;
}
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    MyThreadBalancer *myThreadBalancer;
 
protected:
   void paintEvent(QPaintEvent *event);
   void mousePressEvent(QMouseEvent *e);
   void keyPressEvent(QKeyEvent *event);
 
signals:
    void SignalModeWork(int*bal);
 
private slots:
    void slotTimerAlarm();
    void on_write_1_clicked();  // Слот для записи данных из lineEdit_1 в первый объект первого потока
    void on_write_2_clicked();  // Слот для записи данных из lineEdit_1 во второй объект второго потока
 
public slots:
    void onNumberChanged(int *balancer);
    void clearText(bool);
 
private:
    Ui::MainWindow *ui;
    QTimer *timer;
    QThread thread_1;       // Первый поток
    QThread thread_2;       // Второй поток
    ThreadObjectBalancer exampleObject_1;  // первый объект, который будет работать в первом потоке
    ThreadObjectBalancer exampleObject_2;  // второй объект, который будет работать во втором потоке
};
 
#endif // MAINWINDOW_H


mainwindow.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <stdio.h>
#include <QDebug>
#include <QPixmap>
#include <menu_1.h>
 
#include <QKeyEvent>
 
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
 
int ArrayBalanser[260];
int counterBalanser =0;
int latch = 0;
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
       QPixmap myPixmap( "crvd.png" );
 
       if(!myPixmap.isNull())
       {
           ui->label_3->setPixmap(myPixmap);
       }
       else
       {
           qDebug() << "Cannot find picture";
       }
 
       QFont font = ui->label_2->font();
       font.setPointSize(24);
       ui->label_2->setFont(font);
       ui->label_2->setText(QTime::currentTime().toString("hh:mm:ss") + "\n" + QDate::currentDate().toString("dd.MM.yy"));
 
       timer = new QTimer();
       connect(timer, SIGNAL(timeout()), this, SLOT(slotTimerAlarm()));
       timer->start(1000); // И запустим таймер
 
       myThreadBalancer = new MyThreadBalancer(this);
       connect(myThreadBalancer,SIGNAL(NumberChanged(int*)), this, SLOT(onNumberChanged(int*)));
       connect(myThreadBalancer,SIGNAL(Cleartext(bool)), this, SLOT(clearText(bool)));
 
       myThreadBalancer->Stop = false;
       myThreadBalancer->start();
 
 
 
 
 
       ThreadObjectBalancer *first=new ThreadObjectBalancer();
       ThreadObjectBalancer *second=new ThreadObjectBalancer();
       QThread *thread1=new QThread;
       QThread *thread2=new QThread;
       QObject::connect(&thread_1,        SIGNAL(started()),&exampleObject_1, SLOT(run()));
       QObject::connect(thread1, SIGNAL(started()),  first,   SLOT(run()));
       QObject::connect(thread2, SIGNAL(started()),  second,  SLOT(run()));
       QObject::connect(first,   SIGNAL(finished()), thread1, SLOT(quit()));
       QObject::connect(second,  SIGNAL(finished()), thread2, SLOT(quit()));
       first->moveToThread(thread1);
       second->moveToThread(thread2);
       exampleObject_1.setRunning(true);
       exampleObject_2.setRunning(true);
       thread1->start();
       thread2->start();
}
 
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
 
void MainWindow::keyPressEvent(QKeyEvent *event)
{
    switch(event->key()){
    case Qt::Key_Up:
 
             qDebug()<<"Press Up";
               break;
 
           case Qt::Key_Down:
              qDebug()<<"Press Down";
               break;
 
           case Qt::Key_Enter:
            exampleObject_1.setRunning(false);
            exampleObject_2.setRunning(false);
 
              qDebug()<<"Press Enter";
               break;
 
           case Qt::Key_Left:
              qDebug()<<"Press Left";
               break;
 
           case Qt::Key_Right:
               qDebug()<<"Press Right";
                break;
    }
 
     QMainWindow::keyPressEvent(event);
}


Не могу остановить поток. Нажима. кнопку enter поток продолжает работать. Смотрел в отладчик переменная m_running не меняет свое значение при вызове setRunning.
0
фрилансер
 Аватар для Алексей1153
6501 / 5734 / 1134
Регистрация: 11.10.2019
Сообщений: 15,355
26.11.2019, 08:44
Alex_Golubev, по-моему, сигнал runningChanged ни с чем не соединён.

Либо можно ещё вызвать

[slot] void QThread::quit()
или
void QThread::exit(int returnCode = 0)
0
2 / 2 / 2
Регистрация: 27.02.2016
Сообщений: 247
26.11.2019, 09:20  [ТС]
сигнал runningChanged ни с чем не соединён
Я вот не понял с чем его соединить.
Взял пример https://evileg.com/ru/post/152/ там тоже не с чем не соединен.

Добавлено через 4 минуты
У меня qt4.7.8
0
фрилансер
 Аватар для Алексей1153
6501 / 5734 / 1134
Регистрация: 11.10.2019
Сообщений: 15,355
26.11.2019, 10:03
соединять его нужно, видимо, НЕ с объектом потока, так как сам себя поток запустить не сможет. Например, с MainWindow.
В слоте нужно что-то такое

C++
1
2
3
4
5
6
7
8
if(running)
{
    thread->exec();
}
else
{
    thread->quit();
}
0
2 / 2 / 2
Регистрация: 27.02.2016
Сообщений: 247
26.11.2019, 10:39  [ТС]
Прошу мне объяснить почему переменная m_running не изменяет состояние ?
0
фрилансер
 Аватар для Алексей1153
6501 / 5734 / 1134
Регистрация: 11.10.2019
Сообщений: 15,355
26.11.2019, 11:13
Alex_Golubev, проверь в отладчике, в процедуру ThreadObjectBalancer::run() попадаешь? Чему там равна m_running? Если при первом заходе false, то поток прекращает работу

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
void ThreadObjectBalancer::run()
{
    count = 0;
 
    while (m_running)
    {
        count++;
      //  emit sendMessage(m_message); // Высылаем данные, которые будут передаваться в другой поток
        qDebug() << m_message << " " << m_message_2 << " " << count;
    }
    emit finished();
}
если прикрепишь проект в зипе, попробую посмотреть, что происходит
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
26.11.2019, 12:08
Alex_Golubev, чтобы кусками код не выкладывать, посмотрите прикрепленный проект. Это простой пример, по нажатию кнопки запускаем поток, по нажатию второй его останавливаем.
Вложения
Тип файла: rar untitled.rar (4.5 Кб, 3 просмотров)
0
2 / 2 / 2
Регистрация: 27.02.2016
Сообщений: 247
26.11.2019, 13:47  [ТС]
Пишет что архив поврежден.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
26.11.2019, 13:50
Цитата Сообщение от Alex_Golubev Посмотреть сообщение
Пишет что архив поврежден.
Обновите архиватор. Запакован WinRar-ом 5.60
0
2 / 2 / 2
Регистрация: 27.02.2016
Сообщений: 247
26.11.2019, 13:51  [ТС]
Вот прикрепил проект
Вложения
Тип файла: rar Tion-pro28.rar (31.8 Кб, 3 просмотров)
0
2 / 2 / 2
Регистрация: 27.02.2016
Сообщений: 247
26.11.2019, 15:05  [ТС]
Меня qt ругает
Кликните здесь для просмотра всего текста

error: QtWidgets: No such file or directory
#include <QtWidgets>
^~~~~~~~~~~
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
26.11.2019, 15:21
Цитата Сообщение от Alex_Golubev Посмотреть сообщение
Меня qt ругает
Версия 4.хх? Тогда замените на #include <QtGui>
И переходите уже на 5-ю версию.
0
2 / 2 / 2
Регистрация: 27.02.2016
Сообщений: 247
26.11.2019, 15:26  [ТС]
Не могу на 5. У меня комп не тянет . Комп тионпро28. Линукс на него портировал и решил qt освоить
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
26.11.2019, 15:29
Цитата Сообщение от Alex_Golubev Посмотреть сообщение
Комп тионпро28
А что не купите какой-нибудь простенький ноут? Всяко лучше чем ваш.
Я вот тоже хочу обновить ноут, но то что хочу слишком дорого на данный момент)
0
2 / 2 / 2
Регистрация: 27.02.2016
Сообщений: 247
26.11.2019, 15:34  [ТС]
Тион про28 это промышленный пк вот https://zao-zeo.ru/catalog/sbc/118-tion-pro28 . Он на imx287.

Добавлено через 37 секунд
Он зараза qt5 не тянет.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
26.11.2019, 15:36
Цитата Сообщение от Alex_Golubev Посмотреть сообщение
Тион про28 это промышленный пк
Да, я видел. Подозреваю, что процесс компиляции на нем не самый быстрый, так что если всерьез занимаетесь-меняйте его на что-то побыстрее.
0
2 / 2 / 2
Регистрация: 27.02.2016
Сообщений: 247
26.11.2019, 15:43  [ТС]
Нет. Компилировать программу ни тионе не надо. Компилируется программа на пк. Когда собираешь ядро подключаешь в buildroot qt и привязываешь внешнее ванилиновое ядро. После
нужно сконфигурировать в Qt Creator'е kit и компилятор:

1. Компилятор (если использовать из builroot):

Tools → Options → Compilers → Add → GCC → C

Compiler path: <...>buildroot/output/host/bin/arm-linux-uclibcgnueabi-gcc

Tools → Options → Compilers → Add → GCC → C++

Compiler path: <...>buildroot/output/host/bin/arm-linux-uclibcgnueabi-g++

2. Kit

Device type: Generic Linux Device

Sysroot: <...>buildroot/output/host/arm-builroot-linux-uclibcgnueabi/sysroot

Compiler: выбрать добавленные в п.1

Qt Version: Manage... → Add.. → <...>buildroot/output/host/bin/qmake

Ну и так далее, написание драйверов правка .dts и т.п.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
26.11.2019, 15:43

Главный поток и вторичный
1. При нажатии на кнопку Start в новом потоке запускается server.AcceptTcpClient() (который возвращает обьект TcpClient соединенного...

Каким синтаксисом запускается вторичный поток?
Каким синтаксисом запускается вторичный поток?

Не получается с вторичного потока обратиться напрямую к объекту из главного потока
Добрый день. Проблема заключается в том что не могу в WPF с вторичного потока обратится на прямую к объекту из главного потока. WPF пока...

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

UiThread, как вынести процесс из главного потока?
Я - новичок в Android. Нужно в этом куске кода реализовать многопоточность. Очистить главный поток от операций, связанных с соединением с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
Модель по догадкам
anaschu 25.08.2026
Прошло две недели. Я уже рассказывал, как разговаривал с сотрудниками у сортировки и как понял, что главная ветка — не про приёмку, а про отбор. Но тогда я думал, что понял механику. На этой неделе я. . .
Запись в регистр сведений независимо от заполненности табличной части
Maks 25.08.2026
Реализация из решения ниже выполнена на нетиповом документе с несколькими табличными частями, разработанного в КА2. Задача: Обеспечить запись документа в регистр сведений независимо от. . .
Ноутбук Альфария
kumehtar 24.08.2026
Встретился тут в сети ноутбук Альфария, примарха Альфа-Легиона. Хотя возможно, это ноутбук Омегона, разумеется. Ну как вам?
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru