Qt 使用 来管理线程。下面来看一个简单的例子:

    有经验的开发者立即指出,这里需要使用线程。这是因为 Qt 中所有界面都是在 UI 线程中(也被称为主线程,就是执行了QApplication::exec()的线程),在这个线程中执行耗时的操作(比如那个循环),就会阻塞 UI 线程,从而让界面停止响应。界面停止响应,用户体验自然不好,不过更严重的是,有些窗口管理程序会检测到你的程序已经失去响应,可能会建议用户强制停止程序,这样一来你的程序可能就此终止,任务再也无法完成。所以,为了避免这一问题,我们要使用 QThread 开启一个新的线程:

    1. class WorkerThread : public QThread
    2. {
    3. Q_OBJECT
    4. public:
    5. WorkerThread(QObject *parent = 0)
    6. : QThread(parent)
    7. {
    8. }
    9. protected:
    10. void run()
    11. {
    12. for (int i = 0; i < 1000000000; i++);
    13. emit done();
    14. }
    15. void done();
    16. };
    17.  
    18. MainWindow::MainWindow(QWidget *parent)
    19. : QMainWindow(parent)
    20. {
    21. QWidget *widget = new QWidget(this);
    22. QVBoxLayout *layout = new QVBoxLayout;
    23. widget->setLayout(layout);
    24. lcdNumber = new QLCDNumber(this);
    25. layout->addWidget(lcdNumber);
    26. QPushButton *button = new QPushButton(tr("Start"), this);
    27. layout->addWidget(button);
    28. setCentralWidget(widget);
    29. QTimer *timer = new QTimer(this);
    30. connect(timer, &QTimer::timeout, [=]() {
    31. static int sec = 0;
    32. lcdNumber->display(QString::number(sec++));
    33. });
    34.  
    35. WorkerThread *thread = new WorkerThread(this);
    36. connect(thread, &WorkerThread::done, timer, &QTimer::stop);
    37. connect(thread, &WorkerThread::finished, thread, &WorkerThread::deleteLater);
    38. connect(button, &QPushButton::clicked, [=]() {
    39. timer->start(1);
    40. thread->start();
    41. });
    42. }

    这是 Qt 线程的最基本的使用方式之一(确切的说,这种使用已经不大推荐使用,不过因为看起来很清晰,而且简单使用起来也没有什么问题,所以还是有必要介绍)。代码看起来很简单,不过,如果你认为 Qt 的多线程编程也很简单,那就大错特错了。Qt 多线程的优势设计使得它使用起来变得容易,但是坑很多,稍不留神就会被绊住,尤其是涉及到与 QObject 交互的情况。稍懂多线程开发的童鞋都会知道,调试多线程开发简直就是煎熬。下面几章,我们会更详细介绍有关多线程编程的相关内容。