Qt線程簡介
從 Qt4.4 版本之后,因?yàn)?QThread 的 run 方法創(chuàng)建新線程這樣實(shí)現(xiàn)與 Qt 設(shè)計的理念不符,Qt 主推使用 moveToThread 方法來創(chuàng)建新線程。QThread應(yīng)該被看做是操作系統(tǒng)線程的接口或控制點(diǎn),而不應(yīng)該包含需要在新線程中運(yùn)行的代碼。需要運(yùn)行的代碼應(yīng)該放到一個QObject的子類中,然后將該子類的對象moveToThread到新線程中。主要操作步驟如下:
- 創(chuàng)建一個繼承QObject類的對象object,創(chuàng)建一個線程QThread對象thread。
- 創(chuàng)建主線程中對象 M 與類對象object鏈接的信號槽。
- 通過類對象object的moveToThread方法將類對象object移動到線程對象thread中。
- 調(diào)用線程對象thread的start方法,啟動線程。
- 對象 M 調(diào)用信號槽,類對象 obj 在新線程thread中處理數(shù)據(jù)(調(diào)用新線程只能通過信號槽來完成,如果要將類對象 obj 的數(shù)據(jù)傳回給對象 M,可以由 obj 發(fā)起對 M 的信號槽)。
具體代碼如下:
1:要放入新線程的Worker類
h 文件:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
/*****************************************************************************************
@copyright 2013-2020
@author qiaowei
@contact weiweiqiao@126.com
@version 1.0
@date 2021-01-09
@brief 工人類,主要方法do_something打印工人對象所在線程的id
******************************************************************************************/
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
signals:
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-24
@brief 調(diào)用Controller::print_thread方法
***************************************************************************/
void result_ready(const QString& content);
public slots:
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-07
@brief 打印Worker對象所在線程id
***************************************************************************/
void do_something();
};
#endif // WORKER_H
cpp 文件:
#include <QtDebug>
#include <QThread>
#include "worker.h"
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::do_something()
{
emit result_ready("Hello");
// int i(0);
// while (i < 20) {
// qDebug() << "I'm working in Worker's thread:" << (quint64) QThread::currentThreadId();
// ++i;
// }
qDebug() << "I'm working in Worker's thread:" << (quint64) QThread::currentThreadId();
}
2:操縱Worker類對象的Controller類
h 文件:
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <QObject>
QT_BEGIN_NAMESPACE
class Worker;
QT_END_NAMESPACE
/*****************************************************************************************
@copyright 2013-2020
@author qiaowei
@contact weiweiqiao@126.com
@version 1.0
@date 2021-01-06
@brief 控制線程創(chuàng)建、啟動
******************************************************************************************/
class Controller : public QObject
{
Q_OBJECT
public:
explicit Controller(QObject *parent = nullptr);
~Controller();
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-06
@brief 將對象worker_移入子線程work_thread_,啟動子線程
***************************************************************************/
void move_work_to_thread();
signals:
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-07
@brief 調(diào)用worker_::do_something方法
***************************************************************************/
void start_running();
public slots:
void print_thread() const;
private:
void setup_connections();
void print_thread_id() const;
private:
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-07
@brief 子線程
***************************************************************************/
QThread* work_thread_;
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-07
@brief 放入子線程work_thread_的對象worker_
***************************************************************************/
Worker* worker_;
};
#endif // CONTROLLER_H
cpp 文件:
#include <QThread>
#include <QtDebug>
#include "controller.h"
#include "worker.h"
Controller::Controller(QObject *parent) :
QObject(parent),
work_thread_(new QThread()),
worker_(new Worker())
{
setup_connections();
print_thread_id();
move_work_to_thread();
}
Controller::~Controller()
{
work_thread_->quit();
work_thread_->wait();
delete work_thread_;
if (nullptr == work_thread_) {
qDebug()<< "nullptr";
} else {
work_thread_ = nullptr;
}
}
void Controller::move_work_to_thread()
{
worker_->moveToThread(work_thread_);
// 啟動子線程。不啟動子線程,worker_對象的方法不會被調(diào)用(因?yàn)檫\(yùn)行的環(huán)境沒啟動)
work_thread_->start();
}
void Controller::print_thread() const
{
// int i(0);
//
// while (i < 20) {
// print_thread_id();
// ++i;
// }
print_thread_id();
}
void Controller::setup_connections()
{
connect(this,
&Controller::start_running,
worker_,
&Worker::do_something);
connect(worker_,
&Worker::result_ready,
this,
&Controller::print_thread);
}
void Controller::print_thread_id() const
{
qDebug()<< "Controller::Controller = " << (quint64) QThread::currentThreadId();
}
觸發(fā)線程的ui類
h 文件:
#ifndef CONTROLLER_DIALOG_H
#define CONTROLLER_DIALOG_H
#include <QDialog>
QT_BEGIN_NAMESPACE
class Controller;
QT_END_NAMESPACE
namespace Ui {
class Controller_dialog;
}
/*****************************************************************************************
@copyright 2013-2020
@author qiaowei
@contact weiweiqiao@126.com
@version 1.0
@date 2021-01-09
@brief 操作多線程的ui
******************************************************************************************/
class Controller_dialog : public QDialog
{
Q_OBJECT
public:
explicit Controller_dialog(QWidget *parent = nullptr);
~Controller_dialog();
private:
void setup_connections();
private:
Ui::Controller_dialog *ui;
Controller* controller_;
};
#endif // CONTROLLER_DIALOG_H
cpp 文件:
#include "controller_dialog.h"
#include "ui_controller_dialog.h"
#include "controller.h"
Controller_dialog::Controller_dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Controller_dialog),
controller_(new Controller())
{
ui->setupUi(this);
setup_connections();
setFixedSize(sizeHint());
}
Controller_dialog::~Controller_dialog()
{
delete ui;
delete controller_;
}
void Controller_dialog::setup_connections()
{
// 啟動新線程
connect(ui->start_button_,
&QPushButton::clicked,
controller_,
&Controller::start_running);
// 關(guān)閉所有窗體,退出程序
connect(ui->quit_button_,
&QPushButton::clicked,
qApp,
&QApplication::closeAllWindows);
}
界面 ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Controller_dialog</class>
<widget class="QDialog" name="Controller_dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>219</width>
<height>83</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="start_button_">
<property name="text">
<string>Start Button</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="quit_button_">
<property name="text">
<string>Quit</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
main 文件:
#include <QApplication>
#include "mainwindow.h"
#include "thread_dialog.h"
#include "controller_dialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Controller_dialog d;
d.show();
return a.exec();
}
運(yùn)行結(jié)果,打印Print_thread、Worker對象的線程號:
文章來源:http://www.zghlxwxcb.cn/news/detail-630350.html
?可以看到打印結(jié)果,Worker 對象在線程 9480,主程序入口在線程 5336文章來源地址http://www.zghlxwxcb.cn/news/detail-630350.html
到了這里,關(guān)于Qt QThread的moveToThread方法使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!