Qt中线程的正确用法

一、线程有两种用法

A:想要某些槽子线程中运行(即子线程运行事件循环,子线程完成较复杂的工作),此种方法是真正完整的线程。

   出处:Qt参考手册 QThread 类

  You can use worker objects by moving them to the thread using QObject::moveToThread().

 1 class Worker : public QObject
 2 {
 3     Q_OBJECT
 4 
 5 public slots:
 6     void doWork(const QString &parameter) {
 7         QString result;
 8         /* ... here is the expensive or blocking operation ... */
 9         emit resultReady(result);
10     }
11 
12 signals:
13     void resultReady(const QString &result);
14 };
15 
16 class Controller : public QObject
17 {
18     Q_OBJECT
19     QThread workerThread;
20 public:
21     Controller() {
22         Worker *worker = new Worker;
23         worker->moveToThread(&workerThread);
24         connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
25         connect(this, &Controller::operate, worker, &Worker::doWork);
26         connect(worker, &Worker::resultReady, this, &Controller::handleResults);
27         workerThread.start();
28     }
29     ~Controller() {
30         workerThread.quit();
31         workerThread.wait();
32     }
33 public slots:
34     void handleResults(const QString &);
35 signals:
36     void operate(const QString &);
37 };

The code inside the Worker's slot would then execute in a separate thread. However, you are free to connect the Worker's slots to any signal, from any object, in any thread. It is safe to connect signals and slots across different threads, thanks to a mechanism called queued connections.

 

B:子线程的槽在主线程中运行(半残模式),只有run函数中的代码在子线程中运行。

  Another way to make code run in a separate thread, is to subclass QThread and reimplement run(). For example:

 1 class WorkerThread : public QThread
 2 {
 3     Q_OBJECT
 4     void run() Q_DECL_OVERRIDE {
 5         QString result;
 6         /* ... here is the expensive or blocking operation ... */
 7         emit resultReady(result);
 8     }
 9 signals:
10     void resultReady(const QString &s);
11 };
12 
13 void MyObject::startWorkInAThread()
14 {
15     WorkerThread *workerThread = new WorkerThread(this);
16     connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
17     connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
18     workerThread->start();
19 }

In that example, the thread will exit after the run function has returned. There will not be any event loop running in the thread unless you call exec().

二、总结

It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run(). This means that all of QThread's queued slots will execute in the old thread. Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread.

When subclassing QThread, keep in mind that the constructor executes in the old thread while run() executes in the new thread. If a member variable is accessed from both functions, then the variable is accessed from two different threads. Check that it is safe to do so.

Note: Care must be taken when interacting with objects across different threads. See Synchronizing Threads for details.

 

posted on 2016-03-17 17:24  蔫头匪  阅读(1124)  评论(0)    收藏  举报