Qt信号与槽函数

connect函数的五个参数表示的意义依次为:sender*, signal, receiver*, slot,connectionTpye

其中槽可以是receiver的成员函数,或者是任意可访问的静态函数。在多线程的情形下:

1. 一个对象的线程就是创建该对象时的线程,而不论该对象的定义是保存在那个线程中;

  比如在thread1中开了个新线程thread2,那么thread2 对象就是定义在thread1中的,即thread2对象本身是属于thread1的,而在thread2的run函数中定义的对象则是属于thread2的。

2. QObject的connect函数有几种连接方式,

      a) DirectConnection,信号发送后槽函数立即执行,由sender的所在线程执行;

      b) QueuedConnection,信号发送后返回,相关槽函数由receiver所在的线程在返回到事件循环后执行;

      c) 默认使用的是Qt::AutoConnection,当sender和receiver在同一个线程内时,采用DirectConnection的方式,当sender和receiver在不同的线程时,采用QueuedConnection的方式。

所以如果发生了跨线程调用,即在线程a中使用了线程b的对象就会报各种错误,如:

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

产生这个问题的原因就是因为sender跟receiver可能是属于不同的线程,可能会导致发出信号的线程与接收信号执行槽函数的线程不同。比如sender发出信号x,让槽函数处理一下某些数据,这些数据显然跟sender是在一个线程的,但执行槽函数的时候线程切换了,就等于在处理别的线程的数据了。

解决办法有:

1,采用直接连接方式,让槽函数在发出信号的对象所依赖的线程中执行,也就是不让信号进入消息队列,直接处理,但是这样貌似需要对线程同步进行处理。

2,将receiver移动至sender的线程,比如在thread1中创建了一个thread2,在thread2的run函数中创建了一个obj。想让obj发出信号,然后thread2对象来处理,那么在创建thread2之后把thread2用moveToThread(thread2)移动到thread2中即可,这样sender跟receiver就在同一个线程中了,不过拘束不推荐这么做

3,文档中推荐的方法为:在run函数中创建一个对象,这个对象肯定是属于thread2的,然后使用thread2作为revcever来处理信号即可

PS:

  1 遇见各种乱起八糟的连接问题,可以make clear把各种.o什么的删了重新编译,或者删掉自动生成的makfile,或者检查pro文件。

  2 一个很清晰明了的例子

  3 既然线程对象本身是属于父线程的,为何在run函数中使用对象的成员不会出现跨线程- -!是说qthread对象本身就可以跨线程访问么。。不明白

发布了10 篇原创文章 · 获赞 5 · 访问量 4433

猜你喜欢

转载自blog.csdn.net/u010059204/article/details/88626205