❶ Qt如何循環創建線程
在Qt中使用多線程,目前就我使用過的有兩種,一是子類化QThread,重寫run函數,在run函數里實現自己的代碼,這一部分代碼通常是比較耗時,或者乾脆直接阻塞的。比如一個while循環,設置一個標志,判斷循環結束。
這樣的例子在網上有很多,就不寫了。
這樣寫的話,會有一些東西需要了解。
子類化QThread的方法,只有run函數裡面的內容是執行在子線程里的,其他的部分,比如槽函數什麼的還是在主線程里執行(假設是在主線程開啟的該子線程)。
還有一種方法,是子類化QObject,新建一個線程,然後使用MoveToThread把這個類的對象移到新建的線程中,這種做法使得它所有的槽函數都是執行在新開辟的線程裡面。
如果直接(QObject對象).abc()的話,這個成員函數是在主進程內執行,可能會出現"QObject::killTimer: timers
cannot be stopped from another thread"的運行錯誤。
使用第二種方法的話,貌似會遇到這樣的問題:如果在一個槽函數中把子線程阻塞,其他的槽函數無法接受來自主線程
❷ Qt線程問題,在主線程中如何控制子線程的執行
我提供兩種比較簡單的解決方案
創建一個Receiver的QObject, 該對象必須生存在你繼承的線程中
要麼給該對象構造對應的信號, 然後與你主線程窗體進行Connect, 一般來說是Queue的Connection
然後在子線程只要Emit你所實現的信號即可
或者用postEvent來解決, 自定義一種Event, 然後持有主線程窗體對象, 然後PostEvent給主線程窗體對象
❸ qt在線程中如何實現
//xx.h
Q_OBJECT
public:
CaptureThread(QObject *parent = 0);
~CaptureThread();
protected:
void run();
private:
CvCapture* m_capture;
//xx.cpp
CaptureThread::CaptureThread(QObject *parent) : QThread(parent), m_capture(0)
{
qDebug() << "CaptureThread::CaptureThread";
m_capture = cvCaptureFromCAM(0);
if (!m_capture)
{
qWarning("No webcam");
emit cameraError(tr("No webcam"));
return;
}
cvGrabFrame(m_capture);
this->setTerminationEnabled(true);//線程能否終止
moveToThread(this);
}
void CaptureThread::run()
{}
❹ QT線程如何使用的
包含QThread頭文件
創建一個對象指針 QThread *myThread;
myThread = new QThread;
myThread->start();
同時需要在新建的QThread線程文件中的run函數裡面添加你想要用的代碼即可。
建議看看QT開發的書,例子很多。也可以看幫主文檔的。
❺ Qt同步線程的幾種方法
Qt同步線程的幾種方法
一、QMutex類
QMutex類就像一把鎖,在互斥量之前上鎖(QMutex::lock()),然後在使用完互斥量之後解鎖(QMutex::unlock())。比如下面的代碼:
[cpp] view plain
void someMethod()
{
mutex.lock();
qDebug()<<"Hello";
qDebug()<<"World";
mutex.unlock();
}
class Thread1 : public QThread
{
protected:
void run()
{
someMethod();
}
};
class Thread2 : public QThread
{
protected:
void run()
{
someMethod();
}
};
如上面的代碼,在函數someMethod裡面有兩條語句,如果有兩個線程啟動之後,這兩個線程都將調用這個函數(run函數即為線程啟動後執行的程序),則可能會出現的結果是Hello Hello World World。但是這並不是我們想要的,我們希望的是每個線程可以一次性執行完someMethod函數裡面的代碼。這個時候我們便可以在函數倆面給函數體加上鎖,然後在結束的時候解鎖。
這里需要注意的是,如果一個線程試圖向一個已經被其它線程上鎖了互斥量上鎖的話,這個線程將被阻塞,直到這個互斥量被解鎖。如果一個線程希望自己在試圖對一個上鎖了的互斥量進行訪問的時候能夠不被阻塞,可以將lock()函數替換為tryLock()函數,這個函數的效果是:如果線程正在試圖訪問的互斥量已經被上鎖了,那麼可以立即返回而不被阻塞。
二、QMutexLocker便利類
使用QMutex對互斥量進行加鎖解鎖比較繁瑣,在一些復雜的函數或者拋出C++異常的函數中都非常容易發生錯誤。可以使用一個方便的QMutexLocker類來簡化對互斥量的處理。首先,QMutexLocker類的構造函數接收一個QMutex對象作為參數並且上鎖,然後在析構函數中自動對其進行解鎖。如下代碼:
[cpp] view plain
QMutex mutex;
void someMethod()
{
QMutexLocker locker(&mutex);
qDebug()<<"Hello";
qDebug()<<"World";
}
這里創建一個QMutexLocker類實例,在這個實例的構造函數中將對mutex對象進行加鎖。然後在析構函數中自動對mutex進行解鎖。解鎖的工作不需要顯示地調用unlock函數,而是根據QMutexLocker對象的作用域綁定在一起了。
三、QReadWriteLock類
前兩種保護互斥量的方法比較絕對,其達到的效果是:不管我要對互斥量做些是什麼,我都要一個人霸佔著,即使我只是看看它,也不能讓別人看。這會使得這個互斥量資源的使用率大大下降,造成資源等待等問題。於是,我們可以對線程對互斥量的操作進行分類:讀和寫。有幾種情況:1、如果我只是看看的話,你也可以看,大家看到的都是正確的;2、如果我要看這個數據,你是不能改的,不然我看到的就不知道是什麼了;3、我在改的時候,你不能看的,我可能會讓你看到不正確的了;4、我在改的時候,你當然不能改了。
因此,我們可以對QMutex鎖進行升級,將其升級為QReadWriteLock,QMutex加鎖的方法是lock(),而QReadWriteLock鎖有兩種鎖法:設置為讀鎖(lockForRead())和寫鎖(lockForWrite())。代碼如下:
QReadWriteLock lock;
void someMethod()
{
lock.lockForRead();
//lock.lockForWrite();
qDebug()<<"Hello";
qDebug()<<"World";
lock.unlock();
}
於是可能有一下三種情況:1、一個線程試圖對一個加了讀鎖的互斥量進行上讀鎖,允許;2、一個線程試圖對一個加了讀鎖的互斥量進行上寫鎖,阻塞;3、一個線程試圖對一個加了寫鎖的互斥量進行上讀鎖,阻塞;一個線程試圖對一個加了寫鎖的互斥量進行上寫鎖,阻塞。
所以可以看出,讀寫鎖比較適用的情況是:需要多次對共享的數據進行讀操作的閱讀線程。
四、QReadLocker便利類和QWriteLocker便利類對QReadWriteLock進行加解鎖
和QMutex與QMutexLocker類的關系類似,關於讀寫鎖也有兩個便利類,讀鎖和寫鎖,QReadLocker和QWriteLocker。它們的構造函數都是一個QReadWriteLock對象,不同的是,在QReadLocker的構造函數裡面是對讀寫鎖進行lockForRead()加鎖操作,而在QWriteLocker的構造函數裡面是對讀寫鎖進行lockForWrite()加鎖操作。然後解鎖操作unlock()都是在析構函數中完成的。
五、信號量QSemaphore
前面的幾種鎖都是用來保護只有一個量的互斥量的。但是還有些互斥量(資源)的數量並不止一個,比如一個電腦安裝了2個列印機,我已經申請了一個,但是我不能霸佔這兩個,你來訪問的時候如果發現還有空閑的仍然可以申請到的。於是這個互斥量可以分為兩部分,已使用和未使用。一個線程在申請的時候,會對未使用到的部分進行加鎖操作,如果加鎖失敗則阻塞,如果加鎖成功,即又有一個資源被使用了,於是則將已使用到的部分解鎖一個。以著名的生產者消費者問題為例,分析問題:生產者需要的是空閑位置存放產品,結果是可取的產品多了一個。於是,我們可以定義兩個信號量:QSemaphore freeSpace和QSemaphore usedSpace,前者是給生產者使用的,後者是給
六、條件觸發QWaitCondition(未完待續、、、)
❻ Qt學習之如何啟動和終止一個線程
終止線程的三種方法:1. 使用退出標志,使線程正常退出,也就是當run方法完成後線程終止。 2. 使用stop方法強行終止線程(這個方法不推薦使用,因為stop和suspend、resume一樣,也可能發生不可預料的結果)。3. 使用interrupt方法中斷線程。 1. 使用退出標志終止線程 當run方法執行完後,線程就會退出。但有時run方法是永遠不會結束的。如在服務端程序中使用線程進行監聽客戶端請求,或是其他的需要循環處理的任務。在這種情況下,一般是將這些任務放在一個循環中,如while循環。如果想讓循環永遠運行下去,可以使用while(true){……}來處理。但要想使while循環在某一特定條件下退出,最直接的方法就是設一個boolean類型的標志,並通過設置這個標志為true或false來控制while循環是否退出。下面給出了一個利用退出標志終止線程的例子。
package chapter2; public class ThreadFlag extends Thread { public volatile boolean exit = false; public void run() { while (!exit); } public static void main(String[] args) throws Exception { ThreadFlag thread = new ThreadFlag(); thread.start(); sleep(5000); // 主線程延遲5秒 thread.exit = true; // 終止線程thread thread.join(); System.out.println("線程退出!"); } }
在上面代碼中定義了一個退出標志exit,當exit為true時,while循環退出,exit的默認值為false.在定義exit時,使用了一個Java關鍵字volatile,這個關鍵字的目的是使exit同步,也就是說在同一時刻只能由一個線程來修改exit的值, 2. 使用stop方法終止線程 使用stop方法可以強行終止正在運行或掛起的線程。我們可以使用如下的代碼來終止線程: thread.stop(); 雖然使用上面的代碼可以終止線程,但使用stop方法是很危險的,就象突然關閉計算機電源,而不是按正常程序關機一樣,可能會產生不可預料的結果,因此,並不推薦使用stop方法來終止線程。 3. 使用interrupt方法終止線程 使用interrupt方法來終端線程可分為兩種情況: (1)線程處於阻塞狀態,如使用了sleep方法。 (2)使用while(!isInterrupted()){……}來判斷線程是否被中斷。 在第一種情況下使用interrupt方法,sleep方法將拋出一個InterruptedException例外,而在第二種情況下線程將直接退出。下面的代碼演示了在第一種情況下使用interrupt方法。
package chapter2; public class ThreadInterrupt extends Thread { public void run() { try { sleep(50000); // 延遲50秒 } catch (InterruptedException e) { System.out.println(e.getMessage()); } } public static void main(String[] args) throws Exception { Thread thread = new ThreadInterrupt(); thread.start(); System.out.println("在50秒之內按任意鍵中斷線程!"); System.in.read(); thread.interrupt(); thread.join(); System.out.println("線程已經退出!"); } }
上面代碼的運行結果如下: 在50秒之內按任意鍵中斷線程! sleep interrupted 線程已經退出! 在調用interrupt方法後, sleep方法拋出異常,然後輸出錯誤信息:sleep interrupted. 注意:在Thread類中有兩個方法可以判斷線程是否通過interrupt方法被終止。一個是靜態的方法interrupted(),一個是非靜態的方法isInterrupted(),這兩個方法的區別是interrupted用來判斷當前線是否被中斷,而isInterrupted可以用來判斷其他線程是否被中斷。因此,while (!isInterrupted())也可以換成while (!Thread.interrupted())。
❼ 請問qt中多線程如何使用, 誰能將步驟描述一下
qt中使用多線程常用的有兩種方式
❽ 誰能說一下在Qt中使用多線程有哪些需要注意的事項呢
在Qt中使用多線程,目前就我使用過的有兩種,一是子類化QThread,重寫run函數,在run函數里實現自己的代碼,這一部分代碼通常是比較耗時,或者乾脆直接阻塞的。比如一個while循環,設置一個標志,判斷循環結束。
這樣的例子在網上有很多,就不寫了。
這樣寫的話,會有一些東西需要了解。
子類化QThread的方法,只有run函數裡面的內容是執行在子線程里的,其他的部分,比如槽函數什麼的還是在主線程里執行(假設是在主線程開啟的該子線程)。
還有一種方法,是子類化QObject,新建一個線程,然後使用MoveToThread把這個類的對象移到新建的線程中,這種做法使得它所有的槽函數都是執行在新開辟的線程裡面。
如果直接(QObject對象).abc()的話,這個成員函數是在主進程內執行,可能會出現"QObject::killTimer: timers
cannot be stopped from another thread"的運行錯誤。
使用第二種方法的話,貌似會遇到這樣的問題:如果在一個槽函數中把子線程阻塞,其他的槽函數無法接受來自主線程