
做 Qt 多线程时经常会看到这样的代码QThread *thread new QThread; Worker *worker new Worker; worker-moveToThread(thread); thread-start();看起来没什么问题。但接下来如果这样写worker-doWork();请问doWork()在主线程还是子线程很多人的第一反应是Worker 都已经 moveToThread 了当然在子线程。其实不是。如果这行代码是在主线程调用的doWork()依然在主线程执行。为什么因为worker-doWork();本质上就是一次普通的 C 函数调用。moveToThread()并不会给成员函数增加什么“自动切线程”的能力。我们可以直接验证void Worker::doWork() { qDebug() current: QThread::currentThread(); qDebug() worker: this-thread(); }然后worker-moveToThread(thread); thread-start(); worker-doWork();你会发现current ! worker也就是说Worker 属于子线程但这次函数调用仍然发生在主线程。这也是 Qt 多线程里一个非常容易产生误解的地方。那怎么让它真正跑到子线程最常见的方式是信号槽。例如connect(this, MainWindow::startWork, worker, Worker::doWork); emit startWork();当MainWindow在主线程而Worker已经属于子线程时Qt 会把这次调用投递到 Worker 所在线程。然后才能在子线程中运行Worker::doWork()才会真正在线程中执行。所以这个坑只需要记住一句话worker-moveToThread(thread);代表的是Worker 属于这个线程。并不代表Worker 的所有成员函数以后都会自动跑到这个线程。直接调用worker-doWork();在哪个线程调用就在哪个线程执行。跨线程工作一般通过signal - slot来完成。moveToThread 改变的是对象的线程归属不是普通函数的调用线程。这个概念弄清楚之后Qt 里面很多“明明开了线程为什么还是卡界面”的问题就比较容易理解了。