Qt之线程(QThread)
2014-01-20 11:40阅读:
QThread类提供了一个平台无关的方式来管理线程。
一个QThread对象在程序控制中管理一个线程。线程在run()中开始执行。默认情况下,run()通过调用exec()启动事件循环并在线程里运行一个Qt的事件循环。
可以使用worker-object通过QObject::moveToThread将它们移动到线程。
class Worker
: public
QObject
{
Q_OBJECT
public slots:
void
doWork(const
QString
¶meter) {
//
...
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
&);
};
Worker槽中的代码将在一个单独的线程中执行,然而,可以将(来自任何对象、在任何线程中)任何信号与该槽自由地连接,在不同的线程里连接信号和槽也是安全的,这要归功于一个叫排队的连接机制(queued
connections)。
另一种使代码运行在一个单独的线程中的方法,是子类化QThread中并重新实现的run()。
例如:
class WorkerThread
:
public
QThread
{
Q_OBJECT
void
run()
Q_DECL_OVERRIDE
{
QString
result;
emit
resultReady(result);
}
signals:
void
resultReady(
const
QString
&s);
};
void
MyObject::startWorkInAThread()
{
WorkerThread
*workerThread
=
new
WorkerThread(
this);
connect(workerThread,
&
WorkerThread::resultReady,
this,
&MyObject::handleResults);
connect(workerThread,
&
WorkerThread::finished,
workerThread,
&
QObject::deleteLater);
workerThread->start();
}
上面的例子中,在run()返回后线程就会退出,在线程中将不会有任何的事件循环运行除非调用exec()。
注意一个线程实例位于实例化它的旧线程中,而非调用run()的新线程中,这意味着所有线程的排队槽将在旧线程中执行。因此,开发人员希望在新线程调用槽必须使用worker-object方法,新槽不应直接在子类化QThread中来实现。
当子类化QThread时,请记住,构造函数在旧线程中执行,然而run()在新线程中执行。如果一个成员变量的访问来自两个函数,然后从两个不同的线程访问变量,需要检查这样做是否安全。
注:用在不同的线程中的对象进行交互时必须小心。详见同步线程(Synchronizing
Threads)。
管理线程
QThread会通知你触发了一个信号当线程
started()和
finished()时,或者使用
isFinished()和
isRunning()来查询线程的状态。
可以通过调用
exit()或
quit()来停止线程。在极端情况下,你可能要强行
terminate()一个执行线程。但是,这样做是危险的。请阅读文档查看
terminate()和
setTerminationEnabled()的详细信息。
从Qt4.8起,可以释放运行刚刚结束的线程对象,通过连接
finished()信号到
QObject::deleteLater()。
使用
wait()来阻塞调用的线程,直到其他线程执行完毕(或者直到指定的时间过去)。
QThread中还提供了静态的、平台独立的休眠功能:
sleep()、
msleep()、
usleep()允许秒,毫秒和微秒来区分,这些函数在Qt5.0中被设为public。
注意:一般情况下,
wait()和
sleep()函数应该不需要,因为Qt是一个事件驱动型框架。而不是
wait(),关心监听信号
finished()。取代
sleep(),可以考虑使用QTimer。
静态函数
currentThreadId()和
currentThread()返回标识当前正在执行的线程。前者返回该线程的平台特定的ID,后者返回一个线程指针。
要设置线程的名称,可以在启动线程之前调用
setObjectName()。如果不调用
setObjectName(),线程的名称将是线程对象的运行时类型(上例中“
WorkerThread”,因为这是QThread子类的类名)。请注意,基于Windows的构建版本目前不可用。
注:
技术在于交流、沟通,转载请注明出处并保持作品的完整性。
作者:╰☆奋斗ing❤孩子` 原文:http://blog.sina.cn/dpool/blog/s/blog_a6fb6cc90101hohu.html?vt=4。