QThread::run

在这里插入代码片执行一个耗时的操作时,多线程是常用的选择,最常见的一个方式或许是继承QThread,然后实现其virtual void run()函数,又或者使用高级类,比如QtConcurrent。总之,好像“回字的四种写法”,当然不同情况下,每种方法各有优略而非孔乙己之纯属不知所云。
Qt的官方文档如下:
void QObject::moveToThread ( QThread * targetThread )

Changes the thread affinity for this object and its children. The object cannot be moved if it has a parent. Event processing will continue in the targetThread.
首先,这个耗时操作需在QObject的子类中实现,并且该QObject的parent为0。

下面的代码,是我最近一个工作的代码片段
// 耗时操作具体执行的类
class Worker : public QObject
{
Q_OBJECT
public:
Worker(QObject* parent = 0);
virtual ~Worker();
signals:
void sglProgress(int val); // 进度信号,[0, 100],指示进度
void sglFinished(); // 结束信号
public slots:
// 开始执行耗时操作的槽函数,结束后调用deleteLater(),析构自己
void start();
};
在具体执行这个耗时操作时的代码如下(我在项目中是在一个事件的槽函数中启动这个耗时操作)

typedef pst::Worker Worker;
void FrmMain::sltWork()
{
Worker* worker = new Worker(0); // parent 需为0
// 连接耗时操作进度和完成信号对应的槽函数
connect(worker, SIGNAL(sglProgress(int)), this, SLOT(sltProgress(int)));
connect(worker, SIGNAL(sglFinished()), this, SLOT(sltFinished()));
QThread* thread = new QThread(0); // 开启一个新线程
worker->moveToThread(thread);
// worker需在线程启动后开启,这也是耗时操作的start()函数是槽函数的原因
connect(thread, SIGNAL(started()), worker, SLOT(start()));
// 耗时操作完成后,线程退出
connect(worker, SIGNAL(sglFinished()), thread, SLOT(quit()));
// 特别说明(1),看后面详细说明
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
// 启动线程
thread->start();
}
特别说明(1):

防止内存泄漏,需要使用deleteLater()函数析构thread,常见的一个bug是这样造成的

connect(worker, SIGNAL(sglFinished()), thread, SLOT(deleteLater()));
看上去好像也没什么,其实,会是一个很不稳定的因素,如果线程相对简单,可以很快quit掉,程序仿佛可以正常运行,而事实上并不总是这样,以为worker的sglFinished()信号同时连接了thread的quit()和deleteLater()两个槽函数,如果quit()还没执行完成时,就执行deleteLater(),会造成软件的崩,或者Destroyed while thread is still running这样的bug()。因此,sglFinished()信号连接了线程quit()函数,线程正常退出后,会释放finished()信号,然后由finished()信号连接线程的deleteLater()槽函数,会使线程安全的退出并析构。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值