之前对线程理解得不深入,所以对Qt的线程机制没有搞清楚,今天写一篇文章总结一下,如有错误,欢迎指出。
首先需要理解线程是什么,线程在代码中的表现其实就是一个函数,只不过这个函数和主线程的函数同时运行,写C语言的都知道,一般代码是从main()函数开始运行的,每个线程都有一个入口函数,main()函数可以看做是主线程的入口函数,从main函数开始执行,主线程就开始了,写过一点代码的都知道,程序是从main()函数开始一条一条地往下执行的,但是有的时候我们需要同时执行A,B两个函数。初学代码时,都是先调用A函数,再调用B函数,这时是A函数执行完毕后再执行B函数,没有达到我们想要同时执行的目的。这时如果把A函数放入另一个线程中执行,那么不需要等到A函数执行完毕,B函数就可以开始执行。C++11中已经有了多线程库,简单示例如下
1 std::thread t(A); 2 B();
你可以随便写两个函数,函数名为A,B。函数内容可以写成输出10000次A(B函数可以输出10000次B,输出次数少了可能会观察不到),你可能会发现A和B会交替出现,这就是A和B在同时执行的证明。多线程在图形界面程序中几乎是必须的,图形界面程序的主线程一般是界面线程,用于响应用户的操作,后台线程用于执行计算,通信等操作,如果不使用多线程,图形界面会因为等待计算数据(当然我说的是大量数据,少量数据你可能会感受不到)而卡住不响应用户的操作。讲到这里你也许对线程有了一个基本的印象。
Qt使用QThread类有两种方式,这个网上可以找到很多资料。
第一种:继承QThread类,自己写一个类(假设为MyThread),重写QThread的run()函数,新线程就会运行run()里面的代码,但是要注意的是只有run()函数里面的代码在新线程里运行,所以你自己的MyThread类里面的槽函数虽然和主线程的信号绑定了,但是只要没有放在run()里面运行,还是运行在主线程中的。
第二种:使用moveToThread(),我下面的示例代码就是使用的moveToThread()方法。QThrad中默认的run()函数启用了事件循环(exec()),所以你移动到线程中的那个对象的所有槽函数均在新线程中执行,不会阻塞主线程。看完示例就明白了。新建一个QApplication工程,把mainwindow.h改成下面的代码
1 // mainwindow.h#ifndef MAINWINDOW_H 2 #define MAINWINDOW_H 3 #include <QApplication> 4 #include <QObject> 5 #include <QEvent> 6 #include <thread> 7 #include <iostream> 8 #include <QThread> 9 #include <QPushButton> 10 #include <QVBoxLayout> 11 #include <QMainWindow> 12 13 // network thread 14 class NetworkThread:public QObject 15 { 16 Q_OBJECT 17 public: 18 NetworkThread() 19 { 20 // do some initial works; 21 } 22 23 signals: 24 void datacoming(int a); 25 26 private: 27 void memberFun(); 28 29 public slots: 30 void testSlot(); 31 void sleepSlot(); 32 }; 33 // network thread class 34 35 // GUI class,run in main thread 36 37 class MyWidget:public QMainWindow 38 { 39 Q_OBJECT 40 41 public: 42 QPushButton *firstButton,*secondButton,*thirdButton; 43 44 QVBoxLayout *layout; 45 QWidget *p; 46 47 public: 48 explicit MyWidget(QWidget *parent); 49 ~MyWidget(); 50 signals: 51 void signalTestStart(int a=0); 52 void startNetworkSleep(); 53 54 public slots: 55 void secondButtonClicked(); 56 }; 57 58 // GUI class 59 60 // csApplication class 61 62 class csApplication:public QApplication 63 { 64 Q_OBJECT 65 66 public: 67 csApplication(int argc,char *argv[]); 68 69 MyWidget *mywindow; 70 NetworkThread *netthd; 71 QThread *t; 72 73 ~csApplication(); 74 75 76 }; 77 78 // csApplication class 79 80 81 #endif // MAINWINDOW_H
把main.cpp改成下面的代码,并删去mainwindow.cpp
1 // main.cpp 2 3 #include "mainwindow.h" 4 5 6 7 // network thread 8 9 void NetworkThread::testSlot() 10 { 11 std::cout<<"\nin testSlot()\n thread id:"<<std::this_thread::get_id()<<std::endl; 12 memberFun(); 13 } 14 15 void NetworkThread::memberFun() 16 { 17 std::cout<<"\nin NetworkThread::memberFun()\nthread id:"<<std::this_thread::get_id()<<"\n"<<std::endl; 18 } 19 20 void NetworkThread::sleepSlot() 21 { 22 std::cout<<"in NetworkThread::sleepSlot()\n thread id:"<<std::this_thread::get_id()<<"\nthen sleep 5 seconds\n"; 23 QThread::sleep(5); 24 std::cout<<"sleepSlot() weak up\n"<<std::endl; 25 } 26 27 // network thread class 28 29 // GUI class,run in main thread 30 31 MyWidget::MyWidget(QWidget *parent=0) 32 { 33 firstButton = new QPushButton(tr("first")); 34 secondButton = new QPushButton(tr("second")); 35 thirdButton = new QPushButton(tr("third")); 36 37 layout = new QVBoxLayout; 38 layout->addWidget(firstButton); 39 layout->addWidget(secondButton); 40 layout->addWidget(thirdButton); 41 42 p=new QWidget; 43 44 p->setLayout(layout); 45 46 setCentralWidget(p); 47 48 } 49 MyWidget::~MyWidget() 50 { 51 delete firstButton; 52 delete secondButton; 53 delete thirdButton; 54 delete p; 55 delete layout; 56 } 57 58 void MyWidget::secondButtonClicked() 59 { 60 emit startNetworkSleep(); 61 std::cout<<"in MyWidget::secondButtonClicked()\n thread id: "<<std::this_thread::get_id()<<"\n"<<std::endl; 62 } 63 64 // GUI class 65 66 // csApplication class 67 68 csApplication::csApplication(int argc, char *argv[]):QApplication(argc,argv) 69 { 70 71 std::cout<<"\nin csApplication()\nthread id:"<<std::this_thread::get_id()<<"\n"<<std::endl; 72 mywindow = new MyWidget(); 73 netthd = new NetworkThread(); 74 t = new QThread(); 75 76 connect(mywindow->firstButton,SIGNAL(clicked()),netthd,SLOT(testSlot()),Qt::QueuedConnection); 77 connect(mywindow->secondButton,SIGNAL(clicked()),mywindow,SLOT(secondButtonClicked())); 78 connect(mywindow,SIGNAL(startNetworkSleep()),netthd,SLOT(sleepSlot()),Qt::QueuedConnection); 79 80 netthd->moveToThread(t); 81 t->start(); 82 mywindow->show(); 83 84 } 85 csApplication::~csApplication() 86 { 87 delete mywindow; 88 delete netthd; 89 delete t; 90 } 91 92 // csApplication class 93 94 95 int main(int argc, char *argv[]) 96 { 97 csApplication a(argc, argv); 98 99 return a.exec(); 100 }
点击运行就可以了。
标签:csApplication,多线程,函数,示例,void,线程,include,public,Qt From: https://www.cnblogs.com/ybqjymy/p/18045143