qt线程实用写法

 第一种 QtConcurrent::run

.pro
QT       += concurrent

#include <QFutureWatcher>
#include <QtConcurrent>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private slots:
    /*! \fn  StartThread
    \brief 开启线程
    param [in] obj 类对象
    \return void
    */
    static void StartThread(MainWindow *obj);

    /*! fn  ThreadFinished
    brief   线程完成
    return void
    */
    void ThreadFinished();

private:
    /*! var  future_watcher_
    brief  监听线程完成*/
    QFutureWatcher<void> *future_watcher_;
};
class MyClass {
public:
    void myMethod(int arg) {
        // 在后台线程中执行的代码
    }
};

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

     //new监听线程对象
    future_watcher_  = new QFutureWatcher<void>(this);       

    //开启同步线程
    QFuture<void> f = QtConcurrent::run(QThreadPool::globalInstance(),StartThread,this); 
    //监视该异步操作的执行状态
    future_watcher_->setFuture(f);

    //使用函数指针
    QFuture<void> future = QtConcurrent::run(myFunction, 42);

    //成员函数指针
    MyClass obj;
    QFuture<void> future = QtConcurrent::run(&obj, &MyClass::myMethod, 42);
    

//线程完成  
connect(future_watcher_,&QFutureWatcher<void>::finished,this,&MainWindow::ThreadFinished);   

    //开启等待框
    QProgessIndicatorWidget::GetInstance()->SetProgessIndicatorText("加载提示……");
    QProgessIndicatorWidget::GetInstance()->ProgessIndicatorStart();
    QProgessIndicatorWidget::GetInstance()->show();

}

void myFunction(int arg) {
    // 在后台线程中执行的代码
}


MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::StartThread(MainWindow *obj)
{
    
}

void MainWindow::ThreadFinished()
{
    QProgessIndicatorWidget::GetInstance()->ProgessIndicatorStop();
    QProgessIndicatorWidget::GetInstance()->close();
}

第二种 moveToThread

QThread *Thread = new QThread;
m_classManager = new Classanager;
m_classManager->moveToThread(Thread);
connect(Thread, &QThread::started, m_classManager, &Classanager::slotThreadStart, Qt::AutoConnection);
Thread->start();

 第三种 QThreadPool

#include <QRunnable>
#include <QObject>
#include <QDebug>
#include <QThread>
#include <QApplication>
#include <QThreadPool>
#include <QMutexLocker>
class Parent : public QObject {
public:
    //virtual void parentFunction() = 0;可以写成纯虚函数 通用
    void parentFunction() {
        // 确保 parentFunction() 是线程安全的,如果需要,可以在函数内部添加互斥锁
        QMutexLocker locker(&m_mutex);
        // 执行任务逻辑
    }

private:
    QMutex m_mutex;
};

template<typename T>
class MyTask : public QRunnable {
public:
    MyTask(T *parent) : m_parent(parent) {

    }
    void run() override {
        Q_ASSERT(QThread::currentThread() != qApp->thread()); // 断言当前线程不是主线程

        // 执行任务逻辑
        Parent* parentObj = static_cast<Parent*>(m_parent); // 使用 qobject_cast 进行类型转换
        if (parentObj) {
            parentObj->parentFunction(); // 调用 parentFunction() 函数
        }
        qDebug() << "Hello from thread " << QThread::currentThreadId();
    }

private:
    T *m_parent = nullptr;
};

    // 在主线程中创建 Parent 对象
    Parent *m_parent = new Parent;

    // 在主线程中创建 MyTask 对象,并将其添加到全局线程池中
    MyTask<Parent>* task = new MyTask<Parent>(m_parent);
    task->setAutoDelete(true); // 自动删除 QRunnable 对象,避免内存泄漏的问题
    QThreadPool::globalInstance()->start(task);

    // 在程序退出前等待线程池中的任务执行完毕
    QThreadPool::globalInstance()->waitForDone();

第四种 std::thread

std::thread threadObj(可调用对象, 参数1, 参数2, ...);

1、可调用对象:这是线程开始执行的函数或者函数对象。它可以是普通函数、成员函数、lambda 表达式、functor 等。

2、参数1, 参数2, ...:这些是传递给可调用对象的参数。当线程启动时,这些参数会被传递给该函数或者可调用对象。

#include <thread>
#include <mutex>
std::thread* m_pThread;
std::mutex m_mutex;
Classanager *class1 = new Classanager;
// 使用 std::ref 传递引用
m_pThread = new std::thread(&Classanager::ThreadStart, &class1, std::ref(struct()));

void Classanager::ThreadStart(struct aa)
{
    m_mutex.lock();
    //
    m_mutex.unlock();
}

void Classanager::StopThread()
{
	if (m_pThread && m_pThread->joinable())
	{
		m_pThread->join();
		m_pThread = nullptr;
	}
}

1、lpThreadAttributes: 这是一个指向 SECURITY_ATTRIBUTES 结构的指针,用于指定新线程的安全属性。可以为 NULL,表示使用默认的线程安全属性。

2、dwStackSize: 这是一个无符号整数,表示新线程的堆栈大小(以字节为单位)。可以为 0,表示使用默认的堆栈大小。
3、lpStartAddress: 这是一个指向线程函数的指针,它是新线程要执行的函数的入口点。线程函数必须具有以下形式:DWORD WINAPI ThreadProc(LPVOID lpParameter)。
4、lpParameter: 这是一个指向传递给线程函数的参数的指针。可以为 NULL,表示不传递任何参数。
5、dwCreationFlags: 这是一个用于控制线程创建方式的标志位。例如,可以使用 CREATE_SUSPENDED 标志来创建一个挂起的线程,然后再通过 ResumeThread 函数启动它。可以为 0,表示没有特殊标志。
6、lpThreadId: 这是一个指向接收新线程标识符的变量的指针。新线程的标识符将被写入这个变量中。可以为 NULL,表示不需要获取线程标识符。
    CreateThread 函数返回一个新线程的句柄(HANDLE),用于标识和操作该线程。
    需要注意的是,在使用 CreateThread 创建线程后,应使用 CloseHandle 函数关闭线程句柄,以确保资源的正确释放。

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  SIZE_T                dwStackSize,
  LPTHREAD_START_ROUTINE lpStartAddress,
  LPVOID                lpParameter,
  DWORD                 dwCreationFlags,
  LPDWORD               lpThreadId
);
HANDLE hMutex = NULL;
hMutex = CreateMutex(NULL, FALSE, NULL);

HANDLE hThread = CreateThread(NULL, 0, ThreadStart, NULL, 0, NULL);

WaitForSingleObject(hThread, INFINITE);
CloseHandle(hMutex); //销毁互斥锁  
CloseHandle(hThread);//销毁线程2

void WINAPI Classanager::ThreadStart(struct lpParameter)
{
    ThreadData* data = (ThreadData*)lpParameter;
}

qprogessindicatorwidget 动态等待框

QtConcurrent::run操作界面ui的注意事项(2)

第五种 涉及到线程和ui界面交互

QMetaObject::invokeMethod 

  • obj:要调用方法的对象的指针。
  • method:要调用的方法的名称,以字符串形式传递,类似于信号和槽中的写法。
  • type:连接类型,指定了调用方法的线程上下文,通常使用默认值Qt::AutoConnection,表示根据情况自动选择。
  • ret:返回值的泛型参数,用于指定返回值类型。默认情况下,表示没有返回值。
  • val0val1 等:方法的参数,使用泛型参数 QGenericArgument 表示,可以传递零个或多个参数。
public slots:
    int add(int a, int b);

QMetaObject::invokeMethod(this, "add",
                              Qt::DirectConnection,
                              Q_RETURN_ARG(int, 10),
                              Q_ARG(int, 10),
                              Q_ARG(int, 5));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值