当前位置 博文首页 > Allen Roson:QT QThread
QThread类提供了一种独立于平台的方式来管理线程。
A.QThreads开始在run()中执行。默认情况下,run()通过调用exec()启动事件循环,并在线程内运行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 &);
};
Worker槽内的代码将在一个单独的线程中执行。但是,你可以自由地将Worker的插槽连接到任何线程中的任何对象的任何信号。由于一种称为排队连接的机制,跨不同线程连接信号和插槽是安全的。另一种让代码在单独的线程中运行的方法是子类化QThread并重新实现run()。例如:
class WorkerThread : public QThread
{
Q_OBJECT
void run() override {
QString result;
/* ... here is the expensive or blocking operation ... */
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(),否则线程中不会运行任何事件循环。
A.SA.新插槽不应直接实现到子类QThread中。
在对QThread进行子类化时,请记住构造函数在旧线程中执行,而run()在新线程中执行。A.检查这样做是否安全。
注意:在跨不同线程与对象交互时必须小心。有关详细信息,请参见同步线程。
?
管理线程
当线程started()和finished()时,QThread会通过信号通知你,或者你可以使用isFinished()和isRunning()来查询线程的状态。
可以通过调用exit()或quit()来停止线程。在极端情况下,您可能希望强制终止()一个正在执行的线程。然而,这样做是危险的和令人气馁的。详细信息请阅读terminate()和setTerminationEnabled()的文档。
从Qt 4.8开始,可以通过将finished()信号连接到QObject::deleteLater()来解除驻留在刚刚结束的线程中的对象。
使用wait()阻塞调用线程,直到其他线程完成执行(或直到指定的时间过去)。
QThread还提供了静态的、平台独立的睡眠函数:sleep()、msleep()和usleep()分别允许完整的秒、毫秒和微秒分辨率。这些函数是在Qt 5.0中公开的。
注意:wait()和sleep()函数通常是不必要的,因为Qt是一个事件驱动的框架。与其等待(),不如考虑监听finished()信号。与其使用sleep()函数,不如考虑使用QTimer。
静态函数currentThreadId()和currentThread()返回当前执行线程的标识符。前者返回线程的平台特定ID;后者返回一个QThread指针。
要选择将给您的线程提供的名称(例如,由Linux上的ps -L命令标识),您可以在启动线程之前调用setObjectName()。如果你不调用setObjectName(),给你的线程的名字将是你的线程对象的运行时类型的类名(例如,“RenderThread”在Mandelbrot例子的情况下,因为这是QThread子类的名字)。请注意,这目前在Windows上的发布版本中是不可用的。
请参见Qt中的线程支持、QThreadStorage、同步线程、Mandelbrot示例、Semaphores示例和等待条件示例。
?
成员类型说明
enum QThread:优先级
此枚举类型指示操作系统应该如何调度新创建的线程。
常量值 | 数值 | 描述 |
QThread::IdlePriority | 0 | 仅在没有其他线程运行时调度。 |
QThread::LowestPriority | 1 | 设定比QThread::LowPriority更低的优先级。? |
QThread::LowPriority | 2 | 设定比QThread::NormalPriority更低的优先级。 |
QThread::NormalPriority | 3 | 操作系统的默认优先级。 ? |
QThread::HighPriority | 4 | 设定比QThread::NormalPriority更高的优先级。? |
QThread::HighestPriority | 5 | 设定比QThread::HighPriority更高的优先级。 |
QThread::TimeCriticalPriority | 6 | 尽可能提升优先级。 |
QThread::InheritPriority | 7 | 使用与创建线程相同的优先级。?这是默认值。 |
?
?