您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > qt中多线程类qthread的介绍和使用方法
qt中多线程类qthread的介绍和使用方法单线程的(采集–压缩–解压–发送–接收–显示),用timer来刷新视频播放窗口,现在正在研究多线程(代码还在整理中),以后再换成多线程(用qt4的多线程,因为qt4的线程继承于QObject的,线程间可以使用signal-slot机制通信),建议先看看“linux下的tv播放器.doc(网上的资料)”一.把视频显示到界面的方法(1)针对qt4的(视频格式为rgb32)v4l_grab_movie(&v4l_dev);unsignedchar*pBuffer=v4l_dev.buffer;QImageimage(pBuffer,320,240,QImage::Format_RGB32);QPixmappixmap;pixmap=pixmap.fromImage(image);label-setPixmap(pixmap);label-setFixedSize(pixmap.width(),pixmap.height());(2)针对qt3的1)格式为rgb32的QImage*img;unsignedchar*bit=image;setWFlags(getWFlags()|Qt::WRepaintNoErase);img=newQImage((uchar*)bit,MAX_WIDTH,MAX_HEIGHT,32,NULL,0,QImage::IgnoreEndian);bitBlt(this,0,0,img);2)格式为rgb24的intx,y;inti=0;#if0QLabel*label_time;QTimetime=QTime::currentTime();label_time=newQLabel(time.toString(),this,“label_time”);label_time-setGeometry(5,250,160,31);label_time-setAlignment(QLabel::AlignCenter);#endifv4l_grab_movie(&v4l_dev);QStringa;QStringd;QImageimg;unsignedchar*bit=v4l_dev.buffer;QRgb*point;intr,g,b;QPainterpaint;//该步很重要,设置标志//让QWidget在更新窗体时,不擦除原来的窗体//这样可以避免闪屏setWFlags(getWFlags()|Qt::WRepaintNoErase);if(img.create(MAX_WIDTH,MAX_HEIGHT,32,0,QImage::IgnoreEndian)){for(y=0;yMAX_HEIGHT;y++){for(x=0;xMAX_WIDTH;x++){r=(int)bit[i+2];g=(int)bit[i+1];b=(int)bit[i];point=(QRgb*)(img).scanLine(y)+x;*point=qRgb(r,g,b);i+=3;}}}paint.begin(this);QDatedate=QDate::currentDate();d=date.toString();QTimetime=QTime::currentTime();a=time.toString();paint.drawImage(5,5,(img));paint.drawText(20,20,a,-1);paint.drawText(20,30,d,-1);paint.end();二.qt的多线程问题(qt4与qt3有线程是很大不同的)1)如果不用多线程,一般是通过QApplication的消息循环来处理的2)QThread本身是继承于QObject的,为线程间的signal-slot机制打下了基础(Qt4),而qt3的线程不是继承于QObject,不能在线程间使用signal-slot机制(如QObject::connect(Thread,SIGNAL(Log(QString)),this,SLOT(Logslots(QString)))不能应用在qt3中,只能应用在qt4中)3)QObject本身和线程是没关系的,提供signal-slot机制相关信息三.事件和信号的区别(问题:哪什么时候用事件,什么时候用信号呢?是不是不同的线程间用事件,信号不能用在线程间?但现在的qt4可以在线程间发送信号)仔细来看,事件与信号其实并无多大差别,从我们对其需求上来说,都只要能注册事件或信号响应函数,在事件或信号产生时能够被通知到即可。但有一项区别在于,事件处理函数的返回值是有意义的,我们要根据这个返回值来确定是否还要继续事件的处理,比如在QT中,事件处理函数如果返回true,则这个事件处理已完成,QApplication会接着处理下一个事件,而如果返回false,那么事件分派函数会继续向上寻找下一个可以处理该事件的注册方法。信号处理函数的返回值对信号分派器来说是无意义的。另外还有一个需要我们关注的问题是事件和信号处理时的优先级问题。在QT中,事件因为都是与窗口相关的,所以事件回调时都是从当前窗口开始,一级一级向上派发,直到有一个窗口返回true,截断了事件的处理为止。对于信号的处理则比较简单,默认是没有顺序的,如果需要明确的顺序,可以在信号注册时显示地指明槽的位置。在QT中,事件使用了一个事件队列来维护,如果事件的处理中又产生了新的事件,那么新的事件会加入到队列尾,直到当前事件处理完毕后,QApplication再去队列头取下一个事件来处理。而信号的处理方式有些不同,信号处理是立即回调的,也就是一个信号产生后,他上面所注册的所有槽都会立即被回调。这样就会产生一个递归调用的问题,比如某个信号处理器中又产生了一个信号,会使得信号的处理像一棵树一样的展开。四.基于QT4的一个多线程工程实现(网上见到的一个比较好的例子,关于线程任务分配)(网址:)想法:需要模仿ACE异步调用的方法,在一个线程分配任务给工作线程,并等待工作线程完成后返回结果。定义一个线程类:头文件:#ifndefMYTHREAD_H#defineMYTHREAD_H#includeQThread#includeQEvent#defineMETHOD_EVENTQEvent::User+1028classMethodEvent:publicQEvent{public:MethodEvent():QEvent(QEvent::Type(METHOD_EVENT)){}~MethodEvent(){}public:inti;//存储返回值!};classMyThread:publicQThread{Q_OBJECTpublic:MyThread();~MyThread();boolStartThread();boolStopThread();protected:voidrun();voidcustomEvent(QEvent*e);};#endif//MYTHREAD_H实现文件:#include“mythread.h”MyThread::MyThread(){}MyThread::~MyThread(){}boolMyThread::StartThread(){start();//线程启动,调用runreturntrue;}boolMyThread::StopThread(){exit();returnfalse;}voidMyThread::run(){exec();//进入本线程的消息循环}voidMyThread::customEvent(QEvent*e){if(0==e)return;if(METHOD_EVENT!=e-type()){return;}MethodEvent*methodEvent=static_castMethodEvent*(e);if(NULL==methodEvent)return;for(inti=0;i1000000000;++i){methodEvent-i=i;}}主函数:#includeQtCore/QCoreApplication#include“mythread.h”intmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);MyThreadmythread;mythread.StartThread();//启动辅助线程,MethodEventevent;//新建一个任务QCoreApplication::sendEvent(&mythread,&event);//发给工作线程,并阻塞等待intresult=event.i;//得到返回值。returna.exec();}说明:如果不用到返回值,也就是只是简单分配任务的话,可以用postEvent的方法,也就是要new一个event,发给工作线程,工作线程处理完事件后会去删除你new的event,主线程就不管了。换句话说,postEvent马上返回,不管event是否被处理完,两个线程同时在工作。而上面是主线程要等待工作线程完成工作后才可以继续,阻塞在sendEvent上了五.图像循环队列(摄像头的采集数据放到图像循环队列)程序通过建立带共享锁的4帧图像循环队列做为图像采集线程和图像发送线程进行数据交换的公共缓冲区(带共享锁的循环队列在这个网址下有介绍:)能够在通信中更好的对数据进行读写和存储,在程序编写过程中就把数据队列的方式改为了循环队列。通过设定数据存储地址的头指针和尾指针,以及对数据存储长度状态值的判断,从而达到循环队列的目的。当有新的数据到来时,数据的尾指针自动往后移,长度的也做相应的增加。同时判断数据的长度有没有超出BANK的地址范围,如果超出地址范围,则尾指针跳转到头指针之前,继续往后存储数据,形成了循环队列;同样,当从RAM里取走数据时,数据的头指针自动往后移,长度的也做相应的增减。在队列的出队操作中,还要对数据的长度进行判断,如果达到了最大长度,则丢弃后面所有的数据。直到缓存区能有空间继续作队列为止。六.视频采集数据缓冲机制的研究在视频采集系统中,视频数据的采集与发送需要很好的性能,所以需要一个高性能的数据流缓冲机制,在传统的生产者/消费者模型的基础上,提出一种新的数据流缓冲模型(在一份叫做视频会议系统中数据缓冲机制的研究.pdf中有介绍)(一个关于多线程同步的文章:=1080)七.GNU/Linux中解决多线程互斥同步问题的分析和说明(=274716)当解决多线程互斥同步的问题时,经常会有如下几个问题:1.在一个给定的问题中,需要多少个Mutex,多少个Semaphore?有什么规律?2.在对临界区加锁和等待信号量的顺序上有什么要求和规律?3.什么样操作适合放在临界区,什么样的不适合?下面就生产者和消费者问题来分析一些这几个问题.下面是一个简单的实现程序:生产者向数组sharedArray中写入数据,而消费者从该数组中读取数据.#includestdio.h#includepthread.h#includesemaphore.h#includestdlib.h#defineMAXSIZE5/*共享缓冲区的大小*/intsharedArray[MAXSIZE];/*sharedArray是共享缓冲区*/intcurr=-1;/*curr是用来指定sharedArray当前存有数据的最大位置*//*注意,sharedArray和cur
本文标题:qt中多线程类qthread的介绍和使用方法
链接地址:https://www.777doc.com/doc-3620394 .html