1 Qt的线程支持
2 QThread的使用方法
2.1 继承QThread
继承QThread类,并重新实现run函数。
class ExtThread : public QThread {
private:
public:
ExtThread : public QThread;
protected:
void run() {}
};
void test()
{
ExtThread t;
t.start;
t.wait();
}
2.2 使用moveToThread
最规范的使用QThread方法,QObject的moveToThread函数是将对象加入到指定的线程中。
class Worker {
};
int main(int argc, char const *argv[])
{
QCoreApplication app;
QThread thread;
Worker worker;
worker.moveToThread(&thread);
return app.exec();
}
2.3 使用信号/槽
2.4 使用QtConcurrent::run
2.4.1 运行类函数
void Worker::start()
{
QtConcurrent::run(this, &Worker::fun1);
QtConcurrent::run(this, &Worker::fun1);
}
void Worker::fun1()
{
}
void Worker::fun2()
{
}
2.4.2 运行全局函数
void printMes(char*mes)
{
cout<<"pprintMes(char*mes) thread :"<<QThread::currentThreadId()<<endl;
cout<<mes<<endl;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
cout<<"mainthread:"<<QThread::currentThreadId()<<endl;
char* mes= "hello world";
QtConcurrent::run(printMes,mes);
returna.exec();
}
3 场景方案
生命周期 | 场景 | 方案 |
---|---|---|
无死循环 | 线程运行一个方法,方法结束后即退出线程 | 1. 定义一个函数,然后使用QtConcurrent::run() 运行2. 从 QRunnable 派生一个类,并利用全局线程池QThreadPoll::globalInstance()->start() 运行3. 从 QTrhead 派生一个类,重载QThread::run() 函数,然后使用QThread::start 运行 |
无死循环 | 在容器中所有项执行相同的操作。执行过程中使用所有可用的CPU核 |
QtConcurrent 提供map() 函数来将这些操作应用于容器中的每个项,filter() 用于选择容器元素,以及指定一个删减函数的选项来与容器中剩下的元素进行合并 |
无死循环 | 一个耗时的操作必须在另一个线程中运行,在此期间,状态信息必须发到GUI线程 | 使用QThread ,重载run() 函数并根据情况发送信号。使用queued 信号/槽连接GUI线程 |
死循环 | 有一对象位于另一个线程中,将让其根据不同的请求执行不同的操作 | 从QObject 派生一个类并实现必要的槽和信号,将对象移到一个具有事件循环的线程中,并通过queued 信号/槽连接与该对象进行通信 |
死循环 | 对象位于另一个线程中,对象不断执行重复的任务(如轮询某个端口,并与GUI线程通信) | 在工作者线程中使用一个计时器来实现轮询。但是最好的解决方法是完全避免轮询。使用QSocketNotifier 是不错的选择 |
4 注意事项
- QThread如果没有使用继承以及重新实现run方法的话,线程运行完之后,不会产生finish信号。