QThread介绍(译)

QThread类提供了独立于平台的处理线程类。

在程序中,一个QThread对象处理一个线程。QThread通过start方法创建一个新线程,新线程调用run方法(所以在程序中看到的是run方法在新线程中运行。是否只有run方法运行在新线程中?)。默认情况下,run方法通过调用exec方法启动事件循环,并在线程内运行Qt 事件循环。当退出run方法将会终止这个新线程。

你可以通过QObject::moveToThread方法将worker对象移动到某个线程中。

class Worker : public QObject
{
    Q_OBJECT
public 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对象中的slot代码可以在一个独立的线程中运行。但是,你可以使用任何线程中的任何类对象的信号函数(signal)来链接这个槽函数(slot)。通过使用Qt的队列链接(queued connections)链接不同线程中的信号槽是线程安全的。

另一种在独立线程运行的方法是实现QThread类的run方法。例如:

class WorkerThread : public QThread{
    Q_OBJECT    
    void run() Q_DECL_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方法,不会有任何事件循环在此线程中运行。

我们需要理解的是:创建的QThread实例只是存在旧线程中,只有run方法运行在新线程中。这就意味着所有的QThread的队列槽函数只会在旧线程中运行。如果开发者想在新的线程中调用槽函数,只能使用第一个例子;新的槽函数不必再继承QThread的子类重写。

当继承QThread类,构造函数是在旧线程中执行而run方法则是在新线程中实现。如果一个成员字段可以被构造函数和run方法方法访问,那么这个字段也会被2个线程访问。程序员应确保在访问时数据时安全可靠地。

注:当在不同的线程内操作对象进行交互时,可以看同步线程(Synchronizing Threads)的执行细节。


转载于:https://my.oschina.net/weiweiqiao/blog/311832

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值