日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt-线程启动与关闭实例

發布時間:2023/12/18 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt-线程启动与关闭实例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?養成資源回收的好習慣,任何時候都要想起開辟過的內存回收。就是利用關閉窗口時調用槽函數回收掉。

?具體步驟不難,如下:1)退出線程;2)回收子線程;3)釋放子線程對象內存。(與Linux下的C不太一樣.)

? ? //退出子線程
? ? thread->quit();
? ? //回收資源
? ? thread->wait();
? ? delete myT;
/**********************************

Qt創建線程有兩種方式。第一種繼承QThread重寫run函數,需要注意的是只有run函數才在線程中執行,其它函數被父類直接調用時,它執行所在的線程還是在父類所在的線程中。第二種繼承QObject使用moveToThread啟動線程,這也是官方推薦的寫法,比較靈活通用。

第一種 繼承QThread
class ThreadTest: public QThread
{
public:
? ? ThreadTest(QObject* parent = nullptr);
? ? void doWork();
?
protected:
? ? void run();
};
?
void ThreadTest::doWork()
{
? ? QString msg = QString("%1 -> %2 threadid:[%3]")
? ? ? ? ? ? .arg(__FILE__)
? ? ? ? ? ? .arg(__FUNCTION__)
? ? ? ? ? ? .arg((int)currentThreadId());
? ? qDebug() << msg;
}
?
void ThreadTest::run()
{
? ? QString msg = QString("%1 -> %2 threadid:[%3]")
? ? ? ? ? ? .arg(__FILE__)
? ? ? ? ? ? .arg(__FUNCTION__)
? ? ? ? ? ? .arg((int)currentThreadId());
? ? qDebug() << msg;
?
? ? doWork();
?
? ? for(int i=0;i<3;i++)
? ? {
? ? ? ? qDebug() << "doWork:" << i;
? ? ? ? sleep(1);
? ? }
}
主函數調用,這里也打印輸出了主函數的線程ID,又主動去調用了ThreadTest中的doWork函數
? ? qDebug() << "MainThreadid: " << (int)QThread::currentThreadId();
? ? m_pThreadTest = new ThreadTest(this);
? ? connect(m_pThreadTest,&ThreadTest::finished,m_pThreadTest,&ThreadTest::deleteLater);
? ? connect(m_pThreadTest,&ThreadTest::finished,this,&Widget::threadFinished);
? ? m_pThreadTest->doWork();
? ? m_pThreadTest->start();
輸出結果如下

結果證明只有run函數里面才在線程中執行。

第二種 繼承QObject,使用moveToThread
? ? ? ? 這里我們添加了一個變量m_bRun和互斥鎖m_Mutex來保證線程優雅的退出

class MoveToThreadTest : public QObject
{
public:
? ? MoveToThreadTest();
?
public slots:
? ? void doWork();
? ? void start();
? ? void stop();
?
private:
? ? QMutex m_Mutex;
? ? bool m_bRun;
};
?
MoveToThreadTest::MoveToThreadTest()
{
? ? m_bRun = true;
}
?
void MoveToThreadTest::doWork()
{
? ? QString msg = QString("%1 -> %2 threadid:[%3]")
? ? ? ? ? ? .arg(__FILE__)
? ? ? ? ? ? .arg(__FUNCTION__)
? ? ? ? ? ? .arg((int)QThread::currentThreadId());
?
? ? qDebug() << msg;
}
?
void MoveToThreadTest::start()
{
? ? QString msg = QString("%1 -> %2 threadid:[%3]")
? ? ? ? ? ? .arg(__FILE__)
? ? ? ? ? ? .arg(__FUNCTION__)
? ? ? ? ? ? .arg((int)QThread::currentThreadId());
? ? qDebug() << msg;
?
? ? doWork();
?
? ? for(;;)
? ? {
? ? ? ? QThread::sleep(1);
? ? ? ? qDebug() << "isRuning ";
?
? ? ? ? {
? ? ? ? ? ? QMutexLocker locker(&m_Mutex);
? ? ? ? ? ? if(m_bRun == false)
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? }
}
?
void MoveToThreadTest::stop()
{
? ? QString msg = QString("%1 -> %2 threadid:[%3]")
? ? ? ? ? ? .arg(__FILE__)
? ? ? ? ? ? .arg(__FUNCTION__)
? ? ? ? ? ? .arg((int)QThread::currentThreadId());
? ? qDebug() << msg;
?
? ? QMutexLocker locker(&m_Mutex);
? ? m_bRun = false;
}
? ? ? ? 主函數調用,連接了deleteLater讓線程退出時自殺,盡量避免手動調用delete去刪除對象,因為它不安全

? ? qDebug() << "MainThreadid: " << (int)QThread::currentThreadId();
? ? m_pMoveThread = new MoveToThreadTest();
? ? m_pMoveThread->moveToThread(&m_Thread);
? ? connect(&m_Thread,&QThread::started,m_pMoveThread,&MoveToThreadTest::start);
? ? connect(&m_Thread,&QThread::finished,m_pMoveThread,&MoveToThreadTest::deleteLater);
? ? connect(&m_Thread,&QThread::finished,this,&Widget::threadFinished);
? ? m_pMoveThread->doWork();
? ? m_Thread.start();
? ? ? ? 優雅的終結掉線程

void Widget::on_pushButton_clicked()
{
? ? if(m_pMoveThread)
? ? {
? ? ? ? m_pMoveThread->stop();
? ? ? ? m_Thread.quit();
? ? ? ? m_Thread.wait();
? ? }
}
? ? ? ? 輸出結果如下:

? ? ? ? 根據線程ID我們得出,連接started信號的槽函數才是歸屬于線程。

總結
? ? ? ? 線程的創建推薦使用moveToThread的方法,結束線程推薦使用變量+互斥量的形式控制退出,同時連接deleteLater讓線程自殺,盡量避免terminate這種強制性的退出,最好也不要手動delete對象。
?

總結

以上是生活随笔為你收集整理的Qt-线程启动与关闭实例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。