qt提升全局包含_Qt--线程的使⽤(基础到⾼级)
线程是操作系统能够进⾏运算调度的最⼩单位。它被包含在进程之中,是进程中的实际运作单位。⼀条线程指的是进程中⼀个单⼀顺 线程
序的控制流,⼀个进程中可以并发多个线程,每条线程并⾏执⾏不同的任务。
计算机程序常编写专门的workhorse线程执⾏密集计算,从⽽提⾼了程序的执⾏效率。
今天主要介绍Qt线程四种不同的使⽤⽅式,下⾯结合案例具体说明⼀下。
⼀、继承 QThread, 重写 run() ⽅法,在run()⽅法中进⾏费时操作。
这个⽅法在很多教程上都可以了解到,⼤家第⼀个接触的Qt线程操作应该就是它。它的优点是便于理解,缺点是操作繁琐⽽且需要⾃⼰处理线程安全。下⾯是⼀个简单的⽰例。
class WorkerThread : public QThread
{
Q_OBJECT
void run() override {
QString result;
/* ... here is the expensive or blocking operation ... */
/**
while(true)
{
qInfo() << "xxxxx";
}
*/
emit resultReady(result);
}
signals:
void resultReady(const QString&);
};
// ----
void CcObject::startWorkThread()
{
auto *workerThread = new WorkerThread(this);
connect(workerThread, &WorkerThread::resultReady, this, &CcObject::handleResults);
connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
}
另外需要注意如下⼏点:
1. 因为workerThread对象创建于旧线程, 所以它的slots函数和调⽤的⽅法都将在旧线程中执⾏。
2. ⾮线程安全。
3. 依赖于Qt的事件循环。
⼆、使⽤ QObject的 moveToThread⽅法。
官⽅⽐较推荐的⽅法。
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString ¶meter) {
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 &);
};
使⽤时注意:
1. 此⽅法同样依赖于Qt的事件循环。
2. 同样需要注意线程同步问题。
三、使⽤ QThreadPool::globalInstance() 线程池操作。
QThreadPool⽤于管理和回收单个QThread对象,以帮助减少使⽤线程的程序中的线程创建成本。每个Qt应⽤程序都有⼀个全局QThreadPool对象,可以通过调⽤globalInstance()进⾏访问。
以下是⼀个简单的使⽤案例:
class Task : public QRunnable
{
void run() override
{
// 费时操作
qDebug() << "thread run at:" << QThread::currentThread();
}
};
auto *task = new Task();
QThreadPool::globalInstance()->start(task);
注意事项:
1. 默认情况下, ⽤户在调⽤ QThreadPool::globalInstance()->start(task); 之后不需要再关⼼task对象的释放问题,因为
QThreadPool 会⾃动删除 task。当然也可以通过 QRunnable :: setAutoDelete(bool) 调整策略。
2. 在⼀定时间内未使⽤的线程将过期。默认的到期超时为30000毫秒(30秒)。可以使⽤setExpiryTimeout()进⾏调整。当设置到期
超时为负值时将禁⽤到期机制。
3. maxThreadCount()⽅法可以查询最⼤线程数,也可以使⽤setMaxThreadCount()进⾏调整。默认的maxThreadCount()是
QThread::idealThreadCount()。
QtConcurrent模块。
4. QThreadPool是⼀个⽤于管理线程的低级类,⾼级玩法请参照 QtConcurrent模块
四、QtConcurrent模块。(⾼级玩法)
QtConcurrent模块扩展了Qt Core模块中提供的基本线程⽀持,并简化了可在所有可⽤CPU内核上并⾏执⾏的代码的开发。
that make it possible to write multi-threaded programs The QtConcurrent namespace provides high-level APIs that make it possible to write multi-threaded programs without using low-level threading primitives such as mutexes, read-write locks, wait conditions, or
semaphores. Programs written with QtConcurrent automatically adjust the number of threads used according to the semaphores
number of processor cores available. This means that applications written today will continue to scale when deployed on multi-core systems in the future.
此模块简化了⽤户操作,强烈推荐使⽤。
下⾯是⼀个简单的⽰例。
// ⽅法参数为 Function
// 可以处理返回值
QFuture<int> res = QtConcurrent::run([](){
// 费时操作
一个线程可以包含多个进程return 0;
});
// 可以等待处理完成
// 1.阻塞执⾏不阻塞事件循环
// while(!res.isFinished()) {
// wait
// QApplication::processEvents(QEventLoop::AllEvents, 200);
// }
// 2. 阻塞等待
res.waitForFinished();
// 处理返回值
int result = sult();
注意事项:
1. 需要引⼊ Qt Concurrent模块。
2. 可以使⽤ QFutureWatcher 监视 QFuture。以下是⼀个官⽅⽰例:
/
/ Instantiate the objects and connect to the finished signal.
MyClass myObject;
QFutureWatcher<int> watcher;
connect(&watcher, QFutureWatcher<int>::finished, &myObject, &MyClass::handleFinished);
// Start the computation.
QFuture<int> future = QtConcurrent::run(...);
watcher.setFuture(future);
3. ⾮线程安全。
-- 如果我的⽂章有帮到你, ⿇烦留下⼩⼼⼼。(赞同 + 喜欢 + 评论 )
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论