QThread實例代表一個線程,我們可以重新實現QThread::run(),要新建一個線程,我們應該先繼承QThread並重新實現run()函數。
需要注意的是:
1.必須在創建QThread對象之前創建 QApplication (或QCoreApplication)對象。
2. QCoreApplication::exec() 必須只能從主線程調用,不能從QThread線程調用。
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread(QObject *parent = NULL);
~MyThread();
protected:
voidrun();
};
void MyThread::run()
{
for( int count = 0; count < 20; count++ )
{
sleep( 1 );
}
qDebug( "finish!");
}
我們可以在另外的函數這樣調用:
MyThread thread;
thread.start();
thread.wait(); //必須要加的語句,等待thread結束。
當然我們先開的線程可能是要運行很久,會卡住主線程,使用QeventLoop就可以輕松解決此類問題:
MyThread thread;
thread.start();
connect(&thread,SIGNAL(finished ()),&eventLoop,SLOT(quit()));
thread.wait(1);
eventLoop.exec();
接下來我們看QThread的其他屬性和函數:
Qthread的優先級屬性:Priority指示系統如何調度線程。
| Constant |
Value |
Description |
| QThread::IdlePriority |
0 |
scheduled only when no other threads are running. |
| QThread::LowestPriority |
1 |
scheduled less often than LowPriority. |
| QThread::LowPriority |
2 |
scheduled less often than NormalPriority. |
| QThread::NormalPriority |
3 |
the default priority of the operating system. |
| QThread::HighPriority |
4 |
scheduled more often than NormalPriority. |
| QThread::HighestPriority |
5 |
scheduled more often than HighPriority. |
| QThread::TimeCriticalPriority |
6 |
scheduled as often as possible. |
| 7 |
use the same priority as the creating thread. This is the default. |
0到6的優先級跟windows線程相對應的,就多了一個InheritPriority。
非靜態成員函數:
| void |
exit ( int returnCode = 0 ) |
該函數告訴線程退出事件循環和返回代碼returnCode ;通常返回0意味着成功,非0意味着錯誤。
需要注意的是,該函數不像C語言的庫函數exit一樣返回到調用者。除非再次調用QThread::exec(),否則不會再執行任何事件循環。如果QThread::exec()的事件循環沒有運行,接着的QThread::exec()將會立即返回。
這兩個函數看名字就知道意思:
bool QThread::isFinished ()const
如果線程結束,則返回true,否則返回false。
bool QThread::isRunning ()const
如果線程還在運行則返回true,否則返回false
void QThread::setPriority ( Priority priority )
該函數設置了正在運行的線程的優先級。如果線程沒有運行,函數什么也不做,直接返回。跟蹤源碼發現setPriority 的源碼部分如下:
if(!d->running)
{
qWarning("QThread::setPriority:Cannot set priority, thread is not running");
return;
}
需要注意的是:參數不能是InheritPriorty。
case InheritPriority:
default:
qWarning("QThread::setPriority:Argument cannot be InheritPriority");
return;
如果是InheritPriorty,函數也只輸出一個警告便返回了。
優先級參數的影響依賴於操作系統的調度策略。特別是,在不支持線程優先級的系統(如linux)優先級參數將被忽略。
void QThread::setStackSize ( uint stackSize )
該函數設置線程堆棧的最大值。
需要注意的是:
1.必須在線程啟動之前設置
2. 雖然參數是uint類型,傳入負數的話會自動轉換。
3.大部分的操作系統都設置了線程堆棧的最大最小值限制。如果超出了限制線程可能運行失敗。
驗證了一下,當我傳-1進去,stackSize值變成了4294967295。Start函數里調用beginthreadex創建新線程。Beginthreadex里調用CreateThread這是大部分用過windows多線程的程序員都了解的。創建失敗則輸出警告並返回。
d->handle = (Qt::HANDLE)_beginthreadex(NULL, d->stackSize, QThreadPrivate::start,
this, CREATE_SUSPENDED, &(d->id));
if(!d->handle) {
qErrnoWarning(errno, "QThread::start: Failed to create thread");
d->running = false;
d->finished = true;
return;
}
uint QThread::stackSize () const
該函數返回線程堆棧最大值,如果調用setStackSize()設置最大值的話,返回的就是設置的值,否則返回0;
bool QThread::wait ( unsigned long time =ULONG_MAX )
該函數阻塞線程直到滿足以下條件之一;
1. 線程已經執行結束。如果線程結束,該函數返回true。如果線程沒被啟動也會返回true。
2. Time毫秒時間過去了。如果time 為 ULONG_MAX,該函數永遠不會超時。如果超時,函數返回false。
槽函數:
void QThread::quit ()
函數退出事件循環,返回代碼為0.與調用exit(0).一樣的效果。如果線程沒有事件循環則什么也不做。
void QThread::start ( Priority priority =InheritPriority ) [slot]
通過調用開始run(),執行線程。如果線程已經在運行,則什么也不做。
看一下源碼:
Start()調用:
d->handle =(Qt::HANDLE) _beginthreadex(NULL, d->stackSize, QThreadPrivate::start, this,CREATE_SUSPENDED, &(d->id));
創建線程。
unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSEQThreadPrivate::start(void *arg)
{
QThread *thr = reinterpret_cast<QThread*>(arg);
QThreadData *data = QThreadData::get2(thr);
。。。。。
。。。。。。 //中間省略,刪掉了
emitthr->started(); //發送started信號。
QThread::setTerminationEnabled(true);
thr->run(); //運行我們重新實現的代碼。
finish(arg); //該函數發送finished();信號。
return 0;
}
void QThread::terminate ()
終止線程的運行。線程可能不會理解被終止,這依賴於操作系統的調用策略。在terminate()之后調用QThread::wait()同步終止。
終止線程之后,所有等待線程結束的線程都會被喚醒。
void QThread::terminate()
{
Q_D(QThread);
QMutexLocker locker(&d->mutex);
if(!d->running)
return;
if(!d->terminationEnabled) {
d->terminatePending = true;
return;
}
TerminateThread(d->handle, 0);
d->terminated = true;
QThreadPrivate::finish(this, false); //finish函數發送了finished()信號。從而會喚醒所有等待的線程。
}
除非真的有必要,不然不要輕易調用該函數。
QThread * QThread::currentThread ()
函數返回當前正在執行的線程。
Qt::HANDLE QThread::currentThreadId ()
注意:
返回當前運行的線程的句柄。該函數返回的句柄只能內部使用,不能在其他任何程序的代碼中使用。
在windows系統,該返回值是當前線程的偽句柄。不能用作數值比較,函數返回Win32 函數 getCurrentThreadId()返回的DWORD值。而不是 Win32 函數 getCurrentThread()返回的HANDLE值。
int QThread::idealThreadCount ()
函數返回系統可以運行的理想的線程數。
int QThread::idealThreadCount()
{
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
returnsysinfo.dwNumberOfProcessors; //返回系統中的處理器的數目。
}
void QThread::yieldCurrentThread ()
放棄當前線程轉到另外可執行的線程,有系統決定轉到哪個線程。
void QThread::sleep ( unsigned long secs )
void QThread::msleep ( unsigned long msecs )
void QThread::usleep ( unsigned long usecs )
這三個函數是讓線程進入休眠狀態。它們內部都是調用了windows API Sleep。
void QThread::setTerminationEnabled ( bool enabled =true )
設置是否可以終止當前線程。
http://blog.csdn.net/hai200501019/article/details/9535069
