我們在使用QThread的時候,只需要繼承QThread重新實現 run() 函數就可以了,使用起來很方便,接下來就介紹一種實現自定義的類 CThread ,只要繼承 CThread 後,重新實現 run() 函數即可。
關於 QThread 的使用可以參見 使用Qt中的QThread創建線程
或者訪問我的 個人博客主頁 不會飛的紙飛機 ,導航欄中點擊多線程,然後也可以看到這篇文章 使用Qt中的QThread創建線程
首先看一下繼承 CThread 的子類,CalcSumThread (主要實現計算前100個數的和)的實現:
頭文件定義:
#ifndef CALCSUMTHREAD_H
#define CALCSUMTHREAD_H
#include "CThread.h"
class CalcSumThread : public CThread
{
public:
CalcSumThread();
~CalcSumThread();
// 重寫run函數,實現計算0~100個數的和
void run(void) override;
};
#endif
run 函數中的實現:
void CalcSumThread::run(void)
{
int sum = 0;
for (int i = 0; i <= 100; ++i)
sum += i;
std::cout << "Current Thread ID is " << ::GetCurrentThreadId() << ", Result is " << sum << std::endl;
}
調用部分:
CalcSumThread* thread = new CalcSumThread;
thread->start(); // 開啓線程
thread->wait(); // 等待線程結束
運行結果:
Created Thread Success, Id is 22200
Current Thread ID is 22200, Result is 5050
函數 start() 表示開啓線程(激活線程爲可執行狀態)
函數 wait() 表示阻塞等待線程退出(同 std::thread 的 join函數)
那麼這個 CThread 到底時怎麼實現的呢?
下面是 CThread 的完整實現:
頭文件定義:
#ifndef CTHREAD_H
#define CTHREAD_H
#include <Windows.h>
class CThread
{
public:
CThread();
~CThread();
// 線程入口函數
virtual void run(void) = 0;
// 啓動線程
void start(void);
// 等待線程函數
void wait(void);
private:
static DWORD WINAPI threadProc(LPVOID lpParameters);
// 創建線程
void create(void);
// 線程ID
DWORD m_nThreadId = 0;
// 判斷線程是否創建成功
bool m_isCreatedSuccess = true;
// 線程句柄
HANDLE m_threadHandle = nullptr;
};
#endif
源文件:
#include "CThread.h"
#include <iostream>
CThread::CThread()
{
create();
}
CThread::~CThread()
{
}
void CThread::create(void)
{
// 創建線程
HANDLE handle = ::CreateThread(nullptr, 0, CThread::threadProc, this, CREATE_SUSPENDED, &m_nThreadId);
// 判斷是否創建成功
if (handle)
{
m_isCreatedSuccess = true;
std::cout << "Created Thread Success, Id is " << m_nThreadId << std::endl;
}
else
{
std::cout << "Created Thread Failed!!!" << std::endl;
m_isCreatedSuccess = false;
}
m_threadHandle = handle;
}
// 啓動線程
void CThread::start(void)
{
if (!m_isCreatedSuccess)
return;
// 啓動線程
::ResumeThread(m_threadHandle);
}
// 等待線程函數
void CThread::wait(void)
{
if (!m_isCreatedSuccess)
return;
::WaitForSingleObject(m_threadHandle, INFINITE);
}
DWORD WINAPI CThread::threadProc(LPVOID lpParameters)
{
CThread* thisPointer = (CThread*)lpParameters;
// 判斷線程是否創建成功
if (!thisPointer->m_isCreatedSuccess)
return 1;
// 執行自定義入口函數
thisPointer->run();
return 0;
}
本質上是使用了一個靜態函數作爲線程的入口函數,將 this 指針作爲函數的參數傳入。如果不是靜態函數,c++本質上會把非靜態函數默認傳遞一個 this 指針作爲參數,不符合線程入口函數的函數指針類型定義,因此此處必須爲靜態函數。
- Create() 函數中,使用 CreateThread 函數創建線程,關於 CreateThread 這個API的使用可以參見 使用Qt中的QThread創建線程 。
這裏使用參數 CREATE_SUSPENDED 表示,表示創建線程後不立即執行,掛起該線程。
- start() 函數,啓動線程;使用函數 ResumeThread() 表示將線程從掛起狀態變爲激活狀態,操作系統有一個線程掛起參數,當該參數爲0時,線程變爲激活狀態。使用函數 SuspendThread() 是將該參數+1,使用函數 ResumeThread() 是將該參數-1 。
- threadProc() ,線程入口函數,將參數轉爲 this ,然後調用虛函數 run() 。
- wait() 函數,阻塞等待線程執行完成。使用 WaitForSingleObject() 這個Windows API 實現。
作者:douzhq
個人博客:www.douzhq.cn
文章同步(可下載完整代碼): http://www.douzhq.cn/thread_cthread/