一个QThread对象管理一个线程。QThread的执行从run()函数的执行开始,在Qt自带的QThread类中,run()函数通过调用exec()函数来启动事件循环机制,并且在线程内部处理Qt的事件。
QThread只有run函数是在新线程里的,其他所有函数都在QThread生成的线程里
子线程中能不能进行UI操作:
Qt中的UI操作,比如QMainWindow、QWidget之类的创建、操作,只能位于主线程!
主线程负责提供界面,子线程负责无UI的单一任务,通过“信号-槽”与主线程交互。
#include <QObject> #include <QThread> class ThreadFromQThread : public QThread { Q_OBJECT signals: void message(const QString& info); void progress(int present); public: ThreadFromQThread(QObject* par); ~ThreadFromQThread(); void setSomething(); void getSomething(); void setRunCount(int count); void run(); void doSomething(); private: int m_runCount; };
#include "threadhandle.h" #include <QDebug> ThreadFromQThread::ThreadFromQThread(QObject* par) : QThread(par) ,m_runCount(20) { } ThreadFromQThread::~ThreadFromQThread() {
m_thread->wait(); qDebug() << "ThreadFromQThread::~ThreadFromQThread()"; } void ThreadFromQThread::setSomething() { msleep(500); QString str = QString("%1->%2,thread id:%3").arg(__FUNCTION__).arg(__FILE__).arg((int)QThread::currentThreadId()); emit message(str); } void ThreadFromQThread::getSomething() { msleep(500); emit message(QString("%1->%2,thread id:%3").arg(__FUNCTION__).arg(__FILE__).arg((int)QThread::currentThreadId())); } void ThreadFromQThread::setRunCount(int count) { m_runCount = count; emit message(QString("%1->%2,thread id:%3").arg(__FUNCTION__).arg(__FILE__).arg((int)QThread::currentThreadId())); } void ThreadFromQThread::run() { int count = 0; QString str = QString("%1->%2,thread id:%3").arg(__FILE__).arg(__FUNCTION__).arg((int)QThread::currentThreadId()); emit message(str); while(1) { sleep(1); ++count; emit progress(((float)count / m_runCount) * 100); emit message(QString("ThreadFromQThread::run times:%1").arg(count)); doSomething(); if(m_runCount == count) { break; } } } void ThreadFromQThread::doSomething() { msleep(500); emit message(QString("%1->%2,thread id:%3").arg(__FUNCTION__).arg(__FILE__).arg((int)QThread::currentThreadId())) m_thread = new ThreadFromQThread(this) m_thread->setRunCount(10);
connect(m_thread, &ThreadFromQThread::message, this, &Widget::receiveMessage); connect(m_thread, &ThreadFromQThread::progress, this, &Widget::progress); //connect(m_thread, &QThread::finished, this, &Widget::onQThreadFinished);
//善用QObject::deleteLater
和QObject::destroyed
来进行内存管理
//如果是堆分配的话, 可以通过deleteLater
来让线程自杀
//new
出来,这样在析构时就需要调用QThread::wait()
//connect(m_thread, &QThread::finished, m_thread, &QObject::deleteLater); m_thread->start();
//在QThread执行start函数之后,run函数还未运行完毕,再次start,不会发生任何结果,QThread还是继续执行它的run函数,run函数不会被重新调用。
//虽然在线程未结束时调用start不会出现什么结果,但为了谨慎起见,还是建议在start之前进行判断
void Widget::on_pushButton_clicked() { if(m_thread->isRunning()) { return; } m_thread->start(); }