QThread Class

来源:互联网 发布:java一年经验工资 编辑:程序博客网 时间:2024/06/16 05:43

QThread类提供了一种独立于平台的方式来管理线程。

QThread对象管理程序内的线程控制。QThreads在run()中开始执行。默认情况下,run()通过调用exec()启动事件循环,并在线程中运行一个Qt事件循环。

你可以通过来工作对象使用QObject :: moveToThread()将它们移动到线程。

class Worker : public QObject{    Q_OBJECTpublic 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 &);};

Worker的槽函数在独立的线程中执行。而且你可以自由的使用任何信号将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();}

在该实例中,在运行函数返回后线程退出。不会有任何的时间循环运行,除非调用exec( ).

重要的是要记住,实例化的QThread对象保存在旧线程中,而不是在新线程中调用run( ). 这就意味着所有的线程的槽函数都在旧线程中执行。因此,期望在新线程中调用槽函数的开发者必须使用Worker对象连接,新的槽函数不应该被子类直接实施。

当QThread进行子类化时,请记住,在新线程中执行run( )时,构造函数在旧线程中执行。如果两个函数访问成员变量,则两个不同的线程会访问该变量。检查这样做是否安全。

注意:与不同线程上的对象交互时,必须小心。有关详细信息,请参阅同步线程。

线程管理

当线程started( )或者finished( )时,QThread将通过信号通知你,或者可以使用isFinished()isRunning()来查询线程的状态。

您可以通过调用exit( )quit( )来停止线程。在极端情况下,您可能要强制terminate启动一个执行的线程。但是,这样做是危险和沮丧的。请阅读terminate()setTerminationEnabled()的文档以获取详细信息。

从Qt 4.8起,可以通过将finished( )信号关联到到QObject :: deleteLater( )来释放刚刚结束的线程中的对象(connect ( ))。

使用wait( )阻止调用线程,直到另一个线程完成执行(或直到指定的时间过去)。

QThread还提供静态,平台独立的休眠功能:sleep( )msleep( )usleep( )分别允许完整的秒,毫秒和微秒分辨率。这些功能在Qt 5.0中发布。

注意:wait( )sleep( )函数通常是不必要的,因为Qt是一个事件驱动的框架。而不是wait( ),请考虑收听finished( )信号。而不是sleep( )函数,考虑使用QTimer

静态函数currentThreadId( )currentThread( )返回当前正在执行的线程的标识符。前者为线程返回平台特定ID; 后者返回一个QThread指针。

要选择您的线程的名称(例如通过”ps -L“Linux上的命令标识),您可以在启动线程之前调用setObjectName( )。如果不调用setObjectName( ),线程的名称将是线程对象的运行时类型的类名(例如,”RenderThread”在Mandelbrot示例的情况下,因为它是QThread子类的名称)。请注意,这在Windows上的发布版本目前不可用。

See also Thread Support in Qt, QThreadStorage, Synchronizing Threads, Mandelbrot Example, Semaphores Example, and Wait Conditions Example.

成员函数文档
枚举QThread :: Priority
此枚举类型指示操作系统应如何调度新创建的线程。
不变/值/描述
QThread::IdlePriority 0 只有当没有其他线程正在运行时才调度。
QThread::LowestPriority 1 计划比低优先级少。
QThread::LowPriority 2 计划比普通优先级少。
QThread::NormalPriority 3 操作系统的默认优先级。
QThread::HighPriority 4 重点内容, 比普通优先级更频繁。
QThread::HighestPriority 5 预定比HighPriority更频繁。
QThread::TimeCriticalPriority 6 安排尽可能多的时间。
QThread::InheritPriority 7 使用与创建线程相同的优先级。这是默认值。

原创粉丝点击