原创文章欢迎转载,请保留出处。
若有任何疑问建议,欢迎回复。
邮箱:[email protected]
QT上提供QThread类实现多线程编程,这里简单介绍下如何使用QThread类,虽然说本文介绍多线程编程,但是个人认为如果非必要最好不要使用多线程,可以考虑使用QTimer事件或者其他方式来实现。本文实践环境为QT4,其他版本不保证能正确运行。
首先创建一个QT4空白工程,添加main.cpp,代码如下:
#include <qdebug.h>
int main(int argc, char *argv[])
{
while(1)
{
qDebug("main thread");
sleep(1);
}
return 0;
}
注意这里的死循环是为了验证主线程活动时,子线程也在活动。
通过向导创建新的类,其中基础类填写QThread(注意大小写),选上继承QObjecet,如下图所示。
在childthread的头文件添加构造函数和析构函数,这里可以重载构造函数,我后面说明使用带参数的用途。
childthread(QString str);
~childthread();
对应的cpp文件也加入代码:
childthread::childthread(QString str)
{
}
childthread::~childthread()
{
}
这里注意,构造函数是在线程创建时立即执行,下面我们要重载QThread类的run函数是在创建线程后,执行线程控制函数start后才执行。
在头文件声明:
private:
QString print_str;//要输出的字符串
protected:
void run();
修改对应cpp代码:
#include "childthread.h"
#include <qdebug.h>//注意添加头文件
childthread::childthread(QObject *parent) :
QThread(parent)
{
print_str = "default";//默认输出default
}
childthread::childthread(QString str)
{
print_str = str;
}
childthread::~childthread()
{
}
void childthread::run(){
//转换string为char*
QByteArray ba = print_str.toLatin1();
const char *debug_str = ba.data();
while(1){
qDebug(debug_str);
sleep(1);
}
}
注意这里:一定要先实例化QByteArray ba,不能用const char *debug_str = print_str.toLatin1().data(); 也不要用toAnsii().data();
这样就完成了子线程的代码了,下面通过主线程创建子线程。
修改main.cpp代码:
#include <qdebug.h>
#include "childthread.h"
int main(int argc, char *argv[])
{
QString str = "child thread 2";
childthread *t1;
childthread *t2;
t1 = new childthread();//创建线程1
t2 = new childthread(str);//创建线程2
t1->start();//相当于执行线程1的run函数
t2->start();//相当于执行线程2的run函数
while(1)
{
qDebug("main thread");
sleep(1);
}
return 0;
}
接下来编译输出可以在控制台看到3个线程都在同时工作:
另外终止线程使用:
t1->terminate(); //终止线程1
t1->wait(); //阻塞等待
如果你要使用界面绘制函数或者PV操作请继续往下面,如果需要代码可以到http://download.csdn.net/detail/maxwell_nc/8492061下载,建议自己动手打打代码。
这里要注意,在子线程中不要调用界面绘制函数,如果要使用可以采用子线程发射信号,主线程connect信号与槽,槽代码在主线程中执行。
//子线程头文件中定义信号:
signals:
void change();
//子线程cpp:重载的run函数中发射信号
void childThread::run(){
while(1){
emit change();
QCoreApplication::processEvents();//处理事件
}
}
//主线程头文件定义槽
public slots:
void view_update();//绘制界面函数
//主界面cpp连接信号与槽
connect(thread, SIGNAL(change()), this,SLOT(view_update()));
//这里的view_update中可以使用界面绘制函数,保证线程安全。
如果在线程中使用PV操作的话注意,如果PV操作放在子线程中,阻塞的是子线程,如果放在主线程中阻塞的是主线程,(即使调用的程序是在其他线程)