QT January 16, 2020

【QT】多线程 -- 实现多线程的几种方式

Words count 7.7k Reading time 7 mins. Read count 0

前言

假如将一些耗时操作放在UI线程处理,会导致UI卡顿,影响用户使用体验。因此,我们通常会将耗时操作放在新的线程中处理。这就涉及到线程的使用。在qt中,有几种方式启动多线程:

  1. 继承QThread,重新实现run()函数
  2. 使用QObject::moveToThread()函数
  3. 使用QtConcurrent模块

具体实现

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
// 1. 继承QThread
class DemoThread : public QThread
{
Q_OBJECT
public:
explicit DemoThread(QObject *parent = 0);
~DemoThread();

protected:
//QThread的虚函数,不能直接调用,通过start()间接调用
void run();

signals:
//处理完成信号
void processFinished();
};

#endif // MYTHREAD_H

};

void DemoThread::run()
{
// 在该函数中进行业务的耗时操作
// doSomething
//发送完成信号
emit processFinished();
}


// 2. 通过QObject::moveToThread() --- qt assistant 提供的例子
class Worker : public QObject
{
Q_OBJECT

public slots:
void doWork(const QString &parameter) {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}

signals:
void resultReady(const QString &result);
};

class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};


// 3. 使用QtConcurrent模块
// 3.1 不需要处理结果
QtConcurrent::run(this, &Controller::doWork, params);
// 3.2 需要接受处理结果
QFutureWatcher<QVariantMap> *doWorkWatcher = new QFutureWatcher<QVariantMap>;
QFuture<QVariantMap> future = QtConcurrent::run(this, &Controller::doWork, params);
connect(doWorkWatcher, &QFutureWatcher<QVariantMap>::finished, [=]()
{
QVariantMap result = doWorkWatcher->resultAt(0);
doWorkWatcher->deleteLater();
});
doWorkWatcher->setFuture(future);

其他补充

从上边三种方式来说,QtConcurrent的方式相对简单和直观。QtConcurrent是在Qt 4.4开始引入的。当然,作为一个高级api,除了直接调用run外,QtConcurrent还提供了很多的函数适用于其他的应用场景的。这在之后的文章,会详细介绍。

0%