Блокировка сигнала Qt:
Вызов функции через механизм сигнального слота
Сценарий приложения заключается в том, что подпоток активно информирует основной поток о некоторой информации в многопоточности и ожидает, пока основной поток обработает информацию.
Посмотрим на реализацию кода:
мифочит.h/.cpp
//mythread.h :
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread();
~MyThread();
signals:
void slgTest(int iCount);
private:
QTimer* _pTimer;
void run();
private slots:
void sltTimer();
};
//mythread.cpp
MyThread::MyThread():
_pTimer(nullptr)
{
}
MyThread::~MyThread()
{
if(nullptr != _pTimer){
_pTimer->stop();
delete _pTimer;
}
this->quit();
this->wait();
}
void MyThread::run()
{
_pTimer = new QTimer;
connect(_pTimer,&QTimer::timeout,this,&MyThread::sltTimer,Qt::DirectConnection);
_pTimer->start(500);
this->exec();
}
void MyThread::sltTimer()
{
static int s_iCount = 0;
s_iCount++;
qDebug()<<"Thread ID:"<<QThread::currentThreadId()<<" begin";
emit slgTest(s_iCount);
qDebug()<<"Thread ID:"<<QThread::currentThreadId()<<" end";
}
Преимущества этой статьи: бесплатный пакет учебных материалов по разработке Qt, техническое видео, в том числе (фактический боевой проект Qt, основа языка C++, режим разработки C++, введение в программирование Qt, механизм сигнала и слота QT, рисование изображения разработки интерфейса QT , сеть QT, программирование базы данных QT, бой проекта QT, QSS, OpenCV, быстрый модуль, вопросы для интервью и т. д.) ↓↓↓↓↓↓См .
mainwindow.h/.cpp
//mainwindow.h
class mainWindow : public QWidget
{
Q_OBJECT
public:
explicit mainWindow(QWidget *parent = 0);
~mainWindow();
private:
Ui::mainWindow *ui;
MyThread _myThread;
private slots:
void sltReveice(int iCount);
};
//mainwindow.cpp
mainWindow::mainWindow(QWidget *parent) :
QWidget(parent),
ui(new Ui::mainWindow)
{
ui->setupUi(this);
connect(&_myThread,SIGNAL(slgTest(int)),this,SLOT(sltReveice(int)));
_myThread.start();
}
mainWindow::~mainWindow()
{
delete ui;
}
void mainWindow::sltReveice(int iCount)
{
qDebug()<<"Thread ID:"<<QThread::currentThreadId()<<" begin";
QTime current_time =QTime::currentTime();
qDebug()<<"time:"<<"minute:"<<current_time.minute()<<"second:"<<current_time.second()<<"msec:"<<current_time.msec();
qDebug()<<"received data:"<<iCount;
qDebug()<<"Thread ID:"<<QThread::currentThreadId()<<" end";
}
PS: Вот запись кода
1. Конструкция QTimer должна быть внутри функции run(), чтобы реализовать построение функции слота, запускаемой таймером в потоке, а затем выполнять цикл обработки сообщений.
2. Соединение цепочки сигнальных слотов должно быть записано как: connect(_pTimer,&QTimer::timeout,this,&MyThread::sltTimer);
Если это написано как connect(_pTimer,SIGNAL(*),this,SLOT(*)); форма подскажет, что функция слота не может быть связана, причина должна состоять в том, что функция запуска перезаписывает родительский класс QThread, и это in run должен указывать на QThread вместо мифрида.
3. Параметр ссылки слота сигнала таймера в потоке должен быть Qt::DirectConnection
4. Должен быть Q_OBJECT, и определение макроса Q_OBJECT является обязательным требованием для любой реализации сигналов, слотов или атрибутов.
Результат выполнения приведенного выше кода:
Как показано на рисунке выше, проблем с взаимодействием данных между двумя потоками нет, но что, если я буду спать в основном потоке (имитируя трудоемкие функции)
Добавьте usleep(1000) в sltReveice(); (заголовочный файл сна в Linux: #include <unistd.h>)
результат операции:
Как показано на картинке выше, это серьезно рассинхронизировано.
PS: здесь он будет запускаться постоянно, и сигнал будет постоянно стоять в очереди (такой вид очереди должен существовать только в контексте многопоточных приложений)
Теперь установите блокировку подключения(&_myThread, SIGNAL(slgTest(int)), this, SLOT(sltReveice(int)), Qt::BlockingQueuedConnection);
результат операции:
Как показано на рисунке выше, подпотоки теперь аккуратно расположены, и подпотоки ожидают завершения обработки основным потоком.Возвращаясь к началу «вызова функций через механизм сигнального слота», то есть сказать, подпотоки вызывают функцию.
Не по теме: Вышеупомянутая ситуация, когда сигналы, отправленные потоком, постоянно ставятся в очередь.
Программа немного изменена в программе
выше
2. Приватная переменная мифрида выключает таймер, когда он достигает 20
3. Добавьте метод для получения значений приватных переменных для мифрида
код больше не отображается здесь
Результат запуска кода:
Как показано на рисунке выше, таймер закончился, но функция слота основного потока все еще срабатывает.
Метод обработки здесь заключается в отключении при входе в функцию слота и повторном подключении при выходе из функции (код программы и результаты работы больше не будут отображаться)
Функция отключения: отключить
Как отключиться от PS:
1. Большое количество отключенных сигнальных и слотовых функций
Отключить все сигнальные слоты, подключенные к объекту:disconnect(myObject, 0, 0, 0);myObject->disconnect();
Отключить все сигнальные слоты, подключенные к сигналу: disconnect(myObject, SIGNAL(mySignal()), 0, 0);
Разъединить все отношения сигнал-слот между двумя объектами: разъединить(мойОбъект, 0, мойПолучатель, 0);мойОбъект->разъединить(мойПолучатель);
2. Указанный сигнал просто отключается
QMetaObject::Connection dis = connect(....); отключить (дис);
отправитель()->отключить();
Преимущества этой статьи: бесплатный пакет учебных материалов по разработке Qt, техническое видео, в том числе (фактический боевой проект Qt, основа языка C++, режим разработки C++, введение в программирование Qt, механизм сигнала и слота QT, рисование изображения разработки интерфейса QT , сеть QT, программирование базы данных QT, бой проекта QT, QSS, OpenCV, быстрый модуль, вопросы для интервью и т. д.) ↓↓↓↓↓↓См .