Qt線程QThread簡析(8個線程等級,在UI線程里可調用thread->wait()等待線程結束,exit()可直接退出線程,setStackSize設置線程堆棧,首次見到Qt::HANDLE,QThreadData和QThreadPrivate)


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();

QeventLoop;

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.

QThread::InheritPriority

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM