На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела *nix / gcc / Eclipse / Qt / wxWidgets / GTK+
  • При создании темы ОБЯЗАТЕЛЬНО указывайте версию тулкита / библиотеки / компилятора.
  • Перед тем как задать вопрос, сформулируйте его правильно, чтобы вас могли понять.
  • Нарушение Правил может повлечь наказание со стороны модераторов.


Полезные ссылки:
user posted image Boost по-русски
user posted image Qt по-русски
Модераторы: archimed7592
  
> Перенаправить таймер и его функцию на другое ядро процессора. , Qt v.5.11, Astra Linux v.2.12.43.
    На самом начальном этапе запоролся. Как сделать задачу минималистично и чтобы работала? Непонятно, как пользоваться созданным потоком.

    ExpandedWrap disabled
          //Разброс разных задач потоками по ядрам.
          QThread *qThread_Core2 = new QThread;
          //g_qTimer_Read->moveToThread(qThread_Core2); //Если так сделать - функция, приконнекченная к таймеру, - перестает работать. При этом св-во IsActive таймера после запуска ->start() - True.
          //connect(qThread_Core2, SIGNAL(started()), this, SLOT(vTimer_Operations()));
          qThread_Core2->start();
          bool bbb=qThread_Core2->isRunning(); //True.
          
          connect(g_qTimer_Read, SIGNAL(timeout()), this, SLOT(vTimer_Read()));
      Так и не смог. Даже на билдере было с этим проще. Qt - то еще г. В т.ч. конкретная версия Qt, 5.5.1, сейчас мешает своими багами в выделении памяти больших объемов.
        Цитата Сергей85 @
        Так и не смог

        Сергей85, не могу смотреть на твои мучения! :rolleyes:

        Сделал для тебя демонстрационный проект, разбирая который, я надеюсь, ты найдешь для себя ответы на твои вопросы...

        MultiPulti

        user posted image

        По кнопке [►Start] запускаются три потока. В каждом потоке есть свой таймер, который срабатывает по своему интервалу, и передает в GUI-поток свое значение. Которое, соответственно, изменяет "свой" QLabel. Первый поток изменяет значение 1 раз в секунду, второй поток 10 раз в секунду, а третий поток 100 раз в секунду. По нажатии кнопки [Close] потоки останавливаются и уничтожаются, после этого программа завершается.

        MuliPulti.pro
        Скрытый текст

        ExpandedWrap disabled
          QT += core gui
           
          greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
           
          CONFIG += c++11
           
          SOURCES += \
              main.cpp \
              dialog.cpp \
              worker.cpp
           
          HEADERS += \
              dialog.h \
              worker.h
           
          # Default rules for deployment.
          qnx: target.path = /tmp/$${TARGET}/bin
          else: unix:!android: target.path = /opt/$${TARGET}/bin
          !isEmpty(target.path): INSTALLS += target


        main.cpp
        Скрытый текст

        ExpandedWrap disabled
          #include "dialog.h"
           
          #include <QApplication>
           
          int main(int argc, char *argv[])
          {
              QApplication a(argc, argv);
              Dialog w;
              w.show();
              return a.exec();
          }


        dialog.h
        Скрытый текст

        ExpandedWrap disabled
          #ifndef DIALOG_H
          #define DIALOG_H
           
          #include <QtWidgets>
          #include <worker.h>
           
          class Dialog : public QDialog
          {
                  Q_OBJECT
                  QLabel *L1, *L2, *L3;
                  QThread  *Thread1, *Thread2, *Thread3;
                  Worker *Work1, *Work2, *Work3;
                  QVector <QLabel *> Labels;
                  QPushButton *BS, *BC;
           
              public:
           
                  Dialog(QWidget *parent = nullptr);
           
              public slots:
           
                  void SlotStart();
                  void SlotClose();
                  void SlotUpdate(int iNo, int iValue);
           
              signals:
           
                  void SigQuit();
           
          };
          #endif // DIALOG_H


        dialog.cpp
        Скрытый текст

        ExpandedWrap disabled
          #include "dialog.h"
           
          Dialog::Dialog(QWidget *parent)
              : QDialog(parent)
          {
              QGridLayout *G = new QGridLayout;
              L1 = new QLabel("0");
              L2 = new QLabel("0");
              L3 = new QLabel("0");
              Labels.push_back(L1);
              Labels.push_back(L2);
              Labels.push_back(L3);
              BS = new QPushButton(tr("► Start"));
              BC = new QPushButton(tr("Close"));
              G->addWidget(L1, 0, 0, Qt::AlignCenter);
              G->addWidget(L2, 0, 1, Qt::AlignCenter);
              G->addWidget(L3, 0, 2, Qt::AlignCenter);
              G->addWidget(BS, 1, 1);
              G->addWidget(BC, 1, 2);
              setLayout(G);
              setMinimumSize(320, 120);
              connect(BS, &QPushButton::clicked, this, &Dialog::SlotStart);
              connect(BC, &QPushButton::clicked, this, &Dialog::SlotClose);
          }
           
          void Dialog::SlotStart()
          {
              BS->setEnabled(false);
              // создаем нити
              Thread1 = new QThread;
              Thread2 = new QThread;
              Thread3 = new QThread;
              Work1 = new Worker(nullptr, 0, 1000);
              Work2 = new Worker(nullptr, 1, 100);
              Work3 = new Worker(nullptr, 2, 10);
              Work1->moveToThread(Thread1);
              Work2->moveToThread(Thread2);
              Work3->moveToThread(Thread3);
              // коммутируем потоки с GUI потоком (и сами с собой для корректного финиша и удаления)
              connect(Thread1, &QThread::started, Work1, &Worker::SlotProcess);
              connect(Thread2, &QThread::started, Work2, &Worker::SlotProcess);
              connect(Thread3, &QThread::started, Work3, &Worker::SlotProcess);
              connect(Work1, &Worker::SigUpdate, this, &Dialog::SlotUpdate);
              connect(Work2, &Worker::SigUpdate, this, &Dialog::SlotUpdate);
              connect(Work3, &Worker::SigUpdate, this, &Dialog::SlotUpdate);
              connect(this, &Dialog::SigQuit, Thread1, &QThread::quit);
              connect(this, &Dialog::SigQuit, Thread2, &QThread::quit);
              connect(this, &Dialog::SigQuit, Thread3, &QThread::quit);
              connect(Work1, &Worker::SigFinished, Thread1, &QThread::quit);
              connect(Work2, &Worker::SigFinished, Thread2, &QThread::quit);
              connect(Work3, &Worker::SigFinished, Thread3, &QThread::quit);
              connect(Work1, &Worker::SigFinished, Work1, &Worker::deleteLater);
              connect(Work2, &Worker::SigFinished, Work2, &Worker::deleteLater);
              connect(Work3, &Worker::SigFinished, Work3, &Worker::deleteLater);
              connect(Thread1, &QThread::finished, Thread1, &QThread::deleteLater);
              connect(Thread2, &QThread::finished, Thread2, &QThread::deleteLater);
              connect(Thread3, &QThread::finished, Thread3, &QThread::deleteLater);
              Thread1->start();
              Thread2->start();
              Thread3->start();
          }
           
          void Dialog::SlotClose()
          {
              emit SigQuit();
              close();
          }
           
          void Dialog::SlotUpdate(int iNo, int iValue)
          {
              Labels[iNo]->setText(QString::number(iValue));
          }


        worker.h
        Скрытый текст

        ExpandedWrap disabled
          #ifndef WORKER_H
          #define WORKER_H
           
          #include <QObject>
          #include <QTimer>
           
          class Worker : public QObject
          {
                  Q_OBJECT
           
                  int Counter = 0;
                  int No = 0;
                  int Interval = 0;
                  QTimer *Timer;
           
              public:
           
                  explicit Worker(QObject *parent = nullptr, int iNo = 0, int iInterval = 0);
           
              public slots:
           
                  void SlotProcess();
                  void SlotUpdate();
           
              signals:
           
                  void SigUpdate(int No, int iValue);
                  void SigFinished();
          };
           
          #endif // WORKER_H


        worker.cpp
        Скрытый текст

        ExpandedWrap disabled
          #include <QEventLoop>
          #include "worker.h"
           
          Worker::Worker(QObject *parent, int iNo, int iInterval)
              : QObject{parent}, No{iNo}, Interval{iInterval}
          {
          }
           
          void Worker::SlotProcess()
          {
              QEventLoop ev;
              Timer = new QTimer(this);
              Timer->setInterval(Interval);
              connect(Timer, &QTimer::timeout, this, &Worker::SlotUpdate);
              Timer->start();
              ev.exec();
              emit SigFinished();
          }
           
          void Worker::SlotUpdate()
          {
              Counter++;
              emit SigUpdate(No, Counter);
          }



        Некоторые комментарии

        Возможно ты что-то знаешь, возможно не знаешь - поэтому пусть будет.
        1. В коде часто используются котструкции вида B = new QPushButton("Label"), вместо B = new QPushButton(this,"Label"). Многие, даже умудренные опытом тимлиды, утверждают, что будет утечка памяти. Но это бывает только в том случае, если мы инициализировали элемент управления, а потом про него "забыли". Но, как только мы используем addWidget() или addLayout() или setLayout() или (еще есть варианты) - фрэймворк Qt сам пропишет родителя.
        2. QThread - это оболочка для потока, которая позволяет использовать межпоточные сигналы-слоты, потому наследоваться от QThread не нужно. А, как было правильно написано в начальном сообщении, использовать moveToThread()
        3. В пределах одного потока вызов слота происходит путем прямого вызова метода или лямбды, в случае соединения сигнала одного потока со слотом другого потока вызов преобразуется фрэймворком Qt сперва в событие, а потом в вызов метода другого потока
        4. Всю обработку в потоке следует проводить в слотах, а в основном методе "крутить" QEventLoop. Это позволит потоку "слышать" сигналы, см. предыдущий пункт.
        Файл с проектом присоединяю.
        Прикреплённый файлПрикреплённый файлMuliPulti.7z (3,35 Кбайт, скачиваний: 46)
        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
        0 пользователей:


        Рейтинг@Mail.ru
        [ Script execution time: 0,0279 ]   [ 18 queries used ]   [ Generated: 27.04.24, 03:37 GMT ]