Qt中线程之间、线程与进程之间的通信

前言:线程的创建是为了单独执行一个与主进程没有太大关联的任务,而且这个任务比较耗时。线程可以处理一些输入没有输出的任务,但是有时要处理需要输出结果到其它线程或者进程的任务,比如处理大量数据的运算,就需要把计算的结果分时传回给对应的线程或者进程。线程与主进程之间的信号槽机制在主进程中连接,因为线程是在主进程实例化的。信号槽机制的响应不需要子线程执行run函数。

Qt线程间共享数据主要有两种方式:

1)使用共享内存。即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的。

2)使用singal/slot机制,把数据从一个线程传递到另外一个线程。

第一种方法是普遍的方法,第二种是QT特有的,下面主要介绍singal/slot机制。

线程间singal/slot机制通信的规则:

1) 在线程间使用信号槽进行通信时,槽参数必须使用元数据类型的参数;元数据表示QT中已经存在的数据类型。

2) Qt内生的元数据类型,如int double QString等;

3) 如果要用自定义的数据类型,需要在connect之前将其注册(qRegisterMetaType)为元数据类型。

4) 线程间用“信号与槽”传递引用参数的话,要加const,因为const文字常量存在常量区中,生命周期与程序一样的长。这样可以避免slot调用的时候参数的运行期已过而使引用无效。

使用自定义数据,注册为元数据类型的步骤(在接收方使用下面的步骤):

  1. (以自定义TextAndNumber类型为例)
  2. 自定一种类型,在这个类型的顶部包含:#include
  3. 在类型定义完成后,加入声明:Q_DECLARE_METATYPE(TextAndNumber);
  4. 在main()函数中注册这种类型:qRegisterMetaType("TextAndNumber");
  5. 如果还希望使用这种类型的引用,可同样要注册:qRegisterMetaType("TextAndNumber&");
  6. 引用的声明与其它类型的声明有点不同,如5所示,类型和后面的字符之间差了&,其它类型的声明是<>里面的内容和“”之间的字符是一样的。

第二个步骤的QMetaType是在发送方(发送该数据的线程)中自定义,并且声明个定义,由该线程发送包含信息的QMetaType到接收方(接收数据的线程)。

 

QT线程-线程之间、线程-进程之间的通信singal/slot机制例子:

QObject::connect(&myThread,SIGNAL(addRes(int)),this,SLOT(showRes(int)));

总结:

  1.  Qt的信号槽函数只默认支持Qt的类型和C++提供的内建的基本类型,比如int double float等,根本不支持C++的std::string std::vector 自定义的struct类型。所以需要用Qt提供的Q_DECLARE_METATYPE和qRegisterMetaType来声明和注册自定义的类型和C++的其他类型。
  2.  多线程间的信号槽传递,在connect的时候需要以Qt::QueuedConnection的方式,不然以Qt::DirectConnection的方式接收者UI线程会很长时间收不到后台线程发出的信号,或者信号直接丢失都是有可能的

你可能感兴趣的:(Qt学习——C++)