QT多线程程序编写-QThread
这段时间在做毕业设计,ARM网络通信加密相关的课题。通信嘛,要双向实时的通信多线程肯定是跑不了了。
但是我以前没怎么在Linux下写过程序。多线程也是没怎么接触。以前倒是用pthread库的API写过简单的多线程程序。但是线程间并没有什么通信的地方,直接全局变量搞定了。所以也不熟悉多线程怎么同步数据之类的。
这次为了做ARM下的图形界面所以学习了一下QT,QT里面有个线程类——QThread。通过这个写多线程程序更加方便。线程间同步也方便。
QT的文档里有两种使用方法。
第一种复杂点的:
class Worker : public QObject
{
Q_OBJECT
QThread workerThread;
public slots:
void doWork(const QString ¶meter) {
// ...
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, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
这是第一种用法,先创建一个线程类继承自QObject。为什么要继承这个主要是为了让自己的线程类支持QT的signal/slot功能。
这个线程类里面放一个slot,上面例子里的dowork就是一个这样的slot,把线程要做的工作放里面。之后将某个“signal” 关联到这个slot上。只要发射相应的signal,创建好的slot就开始运行了。
当然这里还没创建线程。 在主线程里,或者说控制线程里。声明一个QThread的对象,通过这个对象来创建线程。
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
这里面new一个Worker对象,就相当于创建了一个线程入口函数。那个moveToThread函数相当于把线程入口的控制权交给QThread对象。然后QThread对象用start方法来开启新线程。把dowork这个slot关联到一个signal上,发射那个signal,新线程里就运行dowork slot里的内容了。线程内的消息可以也定义signal关联外部的slot实现数据的交换。
事实上我并没有试第一种方法,所以上面的描述可能不太对。但是看起来似乎是这样的。
我感觉第二种方法简便的多:
class WorkerThread : public QThread
{
Q_OBJECT
void run() {
QString result;
/* expensive or blocking operation */
emit resultReady(result);
}
signals:
void resultReady(const QString &s);
};
void MyObject::startWorkInAThread()
{
WorkerThread *workerThread = new WorkerThread(this);
connect(workerThread, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
workerThread->start();
}
直接继承QThread类,重写run方法就好了。运行start方法新线程就跑起来了。通信可以使用signal/slot机制。另外,类里面可以直接加入一些方法来读写线程类的数据。这样可能不是线程安全的。但是配合一下signal/slot机制确保不同时读写就好了嘛。另外光用来传递线程初始化参数也很方便啊。pthread里的create函数只能传递一个参数。多个参数就要构造结构体多麻烦。