QT多线程方法(不用新建类)QtConcurrent,std::thread,pthread

  • QT中打印当前线程地址:qDebug()<<QString::fromLocal8Bit("当前线程地址: ") << QThread::currentThread();

1. QFuture future=QtConcurrent::run();

  • 在.pro文件加上concurrent,QT += concurrent
//QT线程QtConcurrent头文件
#include <QFuture>
#include <QtConcurrent>
#include <QThreadPool>
//对线程函数进行声明
extern void sloUpdatePointCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud);
//传递函数中会用到的参数 要按照形参的顺序进行书写
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud=cloud1;
//开启线程
QFuture<void> future=QtConcurrent::run(sloUpdatePointCloud,cloud);

2. std::thread

#include <thread>
std::thread t2(function);
t2.detach();

//当无法访问到类的成员函数时可以使用std::bind进行绑定
auto callback=std::bind(&MainWindow::function,this,placeholders::_1);
std::thread t2(callback);
t2.join();

3. pthread

  • window下QT使用pthread参考了这位博主的博客,写的很详细跟着来就可以使用了感谢。
  • 他的主要做法如下:
      1. pthread网址,在这个连接进去下载pthreads-w32-2-9-1-release.zip。(以下路径都换成你自己的路径)
      1. 将pthread文件解压后F:\pthread\Pre-built.2\include里的文件复制到F:\Qt\5.9.9\msvc2017_64\include
      1. 将pthread文件解压后F:\pthread\Pre-built.2\lib\x64里的文件复制到F:\Qt\5.9.9\msvc2017_64\lib
      1. F:\pthread\Pre-built.2\dll\x64里的文件复制到C:\Windows\System32
      1. F:\pthread\Pre-built.2\dll\x86里的文件复制到C:\Windows\SysWOW64
      1. 在头文件处添加#include <pthread.h>#pragma comment(lib, "pthreadVC2.lib")
  • 以上的第2和3步也可以不拷贝,直接在.pro文件里添加以下也行:
//路径换成自己的路径
INCLUDEPATH += F:\pthread\Pre-built.2\include
LIBS += -LF:\pthread\Pre-built.2\lib\x64\
        -lpthreadVC2
  • 编译程序可能会报"timespec""struct"类型重定义的错误
    在这里插入图片描述

  • 在.pro文件的DEFINES +=后面加上HAVE_STRUCT_TIMESPEC
    在这里插入图片描述

  • 示例如下

      1. 首先用pthread_t t1;定义一个线程ID
      1. 然后使用pthread_create(&t1, NULL, function, &param);
      • 其中 t1为创建的线程ID,function为线程中需要运行的程序,param为需要向function中传递的结构体参数
      • 因为function的默认函数形式是void *function(void* arg);,所以默认只能传递一个参数并且还需要在function函数内对传入的参数进行强制类型转换;当需要传递多个参数时可以将参数包装成结构体进行传递,再在function函数内进行解析接收。关于传参这一块,这篇博客写得很好很详细。
      • 当pthread_create中需要运行的函数是类的成员函数时,由于类型不匹配无法使用error: argument of type ‘void* (MainWindow::)(void*)’ does not match ‘void* (*)(void*)’;这个时候需要将function声明为静态函数,即在类内声明时加上static,即static void * function(void* arg);,但是这样function函数内部就无法调用类的动态成员,解决方法是将this指针作为参数传递进去再对类中成员进行调用
  • 示例如下:

#include <pthread.h>
#pragma comment(lib, "pthreadVC2.lib")

class MainWindow : public QMainWindow
{
    
    
    Q_OBJECT
.....
	public: 
	pthread_t t1;
	static void *function(void *arg);
......
}
//需要传递的结构体参数
struct Param
{
    
    
    MainWindow *my;
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
};
//线程运行的函数
void *MainWindow::function(void *arg)
{
    
    
	//对传入的参数进行获取
	Param receiveParam=*(Param*)arg;
	//然后就可以利用receiveParam.my访问类的动态成员了
	receiveParam.my->ui->.....
.....
}
void MainWindow::TreeAndCat()
{
    
    
	pcl::PointCloud<pcl::PointXYZ>::Ptr test_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	......
	//需要传递的参数
	Param Param1;
	Param1.my=this;
	Param1.cloud=test_cloud;
	//创建线程
	pthread_create(&t1,NULL,function,&Param1);
	pthread_join(function,NULL);
	//pthread_detach(function);
}

4. 其他方法(需要新建类)

    1. 新建类继承QThread,通过重写run()函数,调用对象.start()启动线程
    1. 新建类继承QObject ,通过对象.moveToThread(&t1)将其放入线程,连接信号和槽connect(this, SIGNAL(operate(const int)), worker, SLOT(doWork(int)));作再使用对象.start()启动线程。
    1. 线程池QThreadPool
  • 以上三个都只是做了简单介绍,如果需要使用的话可以看看这两篇博客写得很好
  • <Qt 中开启线程的五种方式 作者:lucky-billy>
  • <Qt 中多线程的使用 --作者:苏丙榅>

猜你喜欢

转载自blog.csdn.net/m0_68312479/article/details/127473258