Qt多线程编程中的对象线程与函数执行线程.doc_第1页
Qt多线程编程中的对象线程与函数执行线程.doc_第2页
Qt多线程编程中的对象线程与函数执行线程.doc_第3页
Qt多线程编程中的对象线程与函数执行线程.doc_第4页
Qt多线程编程中的对象线程与函数执行线程.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Qt多线程编程中的对象线程与函数执行线程分类:QT编程多线程2012-03-14 17:467604人阅读评论(6)收藏举报qt多线程编程threadclasssignal 近来用Qt编写一段多线程的TcpSocket通信程序,被其中Qt中报的几个warning搞晕了,一会儿是说“Cannot create children for a parent that is in a different thread”,有时候又是“QSocketNotifier: socket notifiers cannot be enabled from another thread”,还经常又Assert failure:Cannot send events toobjects owned by a different thread,从而导致程序崩溃。 为彻底搞清原因并解决问题,在查阅大量资料和Qt文档之后,理清了其中的机制,也对多线程编程中的QObject对象创建以及connect执行有更清楚的认识: 1. 一个对象的线程就是创建该对象时的线程,而不论该对象的定义是保存在那个线程中; 2. QObject的connect函数有几种连接方式, a) DirectConnection,信号发送后槽函数立即执行,由sender的所在线程执行; b) QueuedConnection,信号发送后返回,相关槽函数由receiver所在的线程在返回到事件循环后执行; c) 默认使用的是Qt:AutoConnection,当sender和receiver在同一个线程内时,采用DirectConnection的方式,当sender和receiver在不同的线程时,采用QueuedConnection的方式。 为了更清楚的理解这些问题,在此特编了个小例子说明一下。首先定义一个从QObject继承的类SomeObject,包含一个信号someSignal和一个成员函数callEmitSignal,此函数用于发送前面的someSignal信号。定义如下:cppview plaincopy1. /defineObjectclasscppview plaincopy1. classSomeObject:publicQObject2. 3. Q_OBJECT4. public:5. SomeObject(QObject*parent=0):QObject(parent)6. voidcallEmitSignal()/用于发送信号的函数7. 8. emitsomeSignal();9. 10. signals:11. voidsomeSignal();12. ;13. 然后再定义一个从QThread继承的线程类SubThread,它包含一个SomeObject的对象指针obj,另外有一个slot函数someSolt,定义如下:cppview plaincopy1. classSubThread:publicQThread2. 3. Q_OBJECT4. public:5. SubThread(QObject*parent=0):QThread(parent)6. virtualSubThread()7. 8. if(obj!=NULL)deleteobj;9. 10. publicslots:11. /slotfunctionconnectedtoobjssomeSignal12. voidsomeSlot();13. public:14. SomeObject*obj;15. ;16. /slotfunctionconnectedtoobjssomeSignal17. voidSubThread:someSlot()18. 19. QStringmsg;20. msg.append(this-metaObject()-className();21. msg.append(:objsthreadis);22. if(obj-thread()=qApp-thread()23. 24. msg.append(MAINthread;);25. 26. elseif(obj-thread()=this)27. 28. msg.append(SUBthread;);29. 30. else31. 32. msg.append(OTHERthread;);33. 34. msg.append(someSlotexecutedin);35. if(QThread:currentThread()=qApp-thread()36. 37. msg.append(MAINthread;);38. 39. elseif(QThread:currentThread()=this)40. 41. msg.append(SUBthread;);42. 43. else44. 45. msg.append(OTHERthread;);46. 47. qDebug()msg;48. quit();49. 这里someSlot函数主要输出了obj所在的线程和slot函数执行线程。 接着从SubThread又继承了3个线程类,分别是SubThread1, SubThread2, SubThread3.分别实现线程的run函数。定义如下:cppview plaincopy1. /definesubthreadclass12. classSubThread1:publicSubThread3. 4. Q_OBJECT5. public:6. SubThread1(QObject*parent=0);7. /reimplementrun8. voidrun();9. ;10. classSubThread2:publicSubThread11. 12. Q_OBJECT13. public:14. SubThread2(QObject*parent=0);15. /reimplementrun16. voidrun();17. ;18. classSubThread3:publicSubThread19. 20. Q_OBJECT21. public:22. SubThread3(QObject*parent=0);23. /reimplementrun24. voidrun();25. ; 在主程序中分别创建3个不同的线程并运行,查看运行结果。cppview plaincopy1. intmain(intargc,char*argv)2. 3. QCoreApplicationa(argc,argv);4. SubThread1*t1=newSubThread1(&a);/由主线程创建5. t1-start();6. SubThread2*t2=newSubThread2(&a);/由主线程创建7. t2-start();8. SubThread3*t3=newSubThread3(&a);/由主线程创建9. t3-start();10. returna.exec();11. 下面我们来分析不同写法的程序,其obj对象所在的线程空间和someSlot函数执行的线程空间分别是怎样的。 首先看SubThread1的实现:cppview plaincopy1. /2. /classSubThread13. /4. SubThread1:SubThread1(QObject*parent)5. :SubThread(parent)6. 7. obj=newSomeObject();/由主线程创建8. connect(obj,SIGNAL(someSignal(),this,SLOT(someSlot();9. 10. /reimplementrun11. voidSubThread1:run()12. 13. obj-callEmitSignal();14. exec();15. 可以看到,obj是在构造函数中被创建的,那么创建obj对象的线程也就是创建SubThread1的线程,一般是主线程,而不是SubThread1所代表的线程。同时由于obj和this(即t1)都位于主线程,所以someSlot函数也是由主线程来执行的。 而在线程SubThread2中,我们把obj对象的创建放到子线程的run函数中,那么obj对象的线程就应该SubThread2代表的线程,即t2,就不再是主线程了。cppview plaincopy1. /2. /classSubThread23. /4. SubThread2:SubThread2(QObject*parent)5. :SubThread(parent)6. 7. obj=0;8. 9. /reimplementrun10. voidSubThread2:run()11. 12. obj=newSomeObject();/由当前子线程创建13. connect(obj,SIGNAL(someSignal(),this,SLOT(someSlot();14. obj-callEmitSignal();15. exec();16. 同时,在connect函数中由于obj和this(这里是t2)不是在同一个线程中,因此会采用QueuedConnection的方式,其slot函数由this对象所在的线程即主线程来执行。这里有一个特别容易误解的地方,就是这个slot函数虽然是子线程SubThread2的一个成员函数,connect操作也是在子线程内完成的,但是该函数的执行却不在子线程内,而是在主线程内。 那么如果想让相应的slot函数在子线程内执行,该如何做呢?在子线程的run函数中创建obj对象的同时,在执行connect时指定连接方式为DirectConnection,这样就可以使slot函数在子线程中运行,因为DirectConnection的方式始终由sender对象的线程执行。如cppview plaincopy1. /2. /classSubThread33. /4. SubThread3:SubThread3(QObject*parent)5. :SubThread(parent)6. 7. obj=0;8. 9. /reimplementrun10. voidSubThread3:run()11. 12. obj=newSomeObject();13. connect(obj,SIGNAL(someSignal(),this,SLOT(someSlot(),14. Qt:DirectConnection);15. obj-callEmitSignal();16. exec()

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论