第一种 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;
}
QtConcurrent::run操作界面ui的注意事项(2)
第五种 涉及到线程和ui界面交互
QMetaObject::invokeMethod
obj
:要调用方法的对象的指针。method
:要调用的方法的名称,以字符串形式传递,类似于信号和槽中的写法。type
:连接类型,指定了调用方法的线程上下文,通常使用默认值Qt::AutoConnection
,表示根据情况自动选择。ret
:返回值的泛型参数,用于指定返回值类型。默认情况下,表示没有返回值。val0
、val1
等:方法的参数,使用泛型参数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));