CWinThread

CWinThread

MFC類。CWinThread類是MFC用來封裝執行緒的,包括UI執行緒和工作者執行緒。因此每個MFC程式至少使用一個CWinThread派生類。被MFC程式設計師熟知的CWinApp套用類就從這裡派生。

基本介紹

  • 中文名:CWinThread
  • 外文名:CWinThread
說明,成員函式,

說明

Windows以訊息驅動方式工作,每個WIN32應用程式都至少包含一個訊息佇列和一個訊息泵。訊息佇列建立在作業系統提供記憶體保留區中,訊息泵不斷搜尋訊息佇列,將取得的訊息分發給應用程式的各個部分進行處理,這個過程叫做訊息循環。基本訊息循環如下:
//從佇列中獲取訊息
while(GetMessage(&msg,0,0,0))
{
//轉換訊息參數
TranslateMesssage(&msg);
//分發訊息
}
Windows以執行緒封裝訊息循環,封裝訊息循環的執行緒叫做用戶界面執行緒,即UI執行緒。該執行緒可以創建並撤銷視窗。此外,還有一種執行緒叫做工作者執行緒,它是輔助UI執行緒工作的,它沒有訊息循環,不能處理系統事件和視窗訊息,也不能關聯主視窗。主執行緒和輔執行緒雖然享有共同的虛擬地址空間,但各自占用獨立的CPU時間片,參與系統資源的競爭。所以,可以使用輔執行緒完成經常性的、耗費機時的數據處理工作(例如網路通信),減輕UI執行緒的負擔,確保UI執行緒及時回響用戶的視窗操作。根據需要,一個應用程式中也可以創建多個UI執行緒。

成員函式

下面介紹幾個實用的CWinThread類成員函式。
虛函式InitInstance
Windows允許同時運行一個應用程式的多個備份,又稱為運行一個程式的多個實例。InitInstance就是“初始化實例”的意思,可見,它是在實例創建時首先被調用的。應用程式總要重載這個虛函式,進行系統設定,創建運行環境。例如,主視窗一定要在InitInstance()中創建,因為該函式退出後就進入該執行緒的訊息循環
虛函式Run
該函式提供UI執行緒訊息循環,即反覆地提取訊息,分發訊息,直到收到WM_QUIT退出循環,執行緒隨即結束。在循環中,如果當前沒有收到訊息,則調用空閒訊息處理程式OnIdle() 。以下是該函式的完整定義。
virtual int CWinThread::Run()
{
ASSERT_VALID(this);
//是否要做空閒處理
BOOL bIdle = TRUE;
//用戶記錄空閒處理已經連線執行的次數
LONG lIdleCount = 0;
//acquire and dispatch messages until a WM_QUIT message is received.
for (;;)
{
//如果空閒狀態為真,且訊息佇列為空,則進行空閒處理
while(bIdle && !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
{
//PeekMessage()用於檢查訊息佇列是否為空,但並不處理訊息
//調用空閒處理程式,如果返回零,說明空閒處理已全部完成
if (!OnIdle(lIdleCount++))
bIdle = FALSE;
}
//空閒處理循環結束,進入訊息泵循環
do
{
//調用訊息泵,提取訊息並分發訊息
//如果收到WM_QUIT訊息,則退出訊息循環
if (!PumpMessage())
return ExitInstance();
//根據剛處理的訊息類型,判斷是否應該在沒有訊息到來時立即進行空閒處理
if (IsIdleMessage(&m_msgCur))
{
bIdle = TRUE;
//在重新進行空閒處理前,清空空閒處理的執行次數
lIdleCount = 0;
}
} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
}
ASSERT(FALSE); //不可能執行的語句
}
PumpMessage
//省略了調試信息的輸出功能
BOOL CWinThread::PumpMessage()
{
ASSERT_VALID(this);
//取出訊息佇列中的第一個訊息,直到取得訊息,該函式才返回
if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
{
//收到WM_QUIT訊息
return FALSE;
}
//處理訊息,但不處理WM_KICKIDLE
if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
{
//轉換虛鍵訊息到字元訊息
::TranslateMessage(&m_msgCur);
//分發訊息
::DispatchMessage(&m_msgCur);
}
return TRUE;
}
閱讀PumpMessage代碼可知,訊息泵並不處理WM_KICKIDLE訊息,收到該訊息後,直接返回。其實,WM_KICKIDLE訊息被用來刺激空閒處理的執行,它作為一個空訊息促使::GetMessage()返回。
雖然Run()是虛擬函式,但很少被重載
虛函式ExitInstance
InitInstance()相反,該函式是在退出訊息循環時執行,一般被框架調用,做最後的清理工作。但如果調用InitInstance()失敗,ExitInstance()也會被調用。可以重載ExitInstance(),為執行緒做相關的清理工作。不要在除重載的Run()函式外的地方調用它。如果將CWinThread成員變數m_bAutoDelete設為TRUE,CWinThread::ExitInstance()會刪除當前的CWinThread對象。所以,如果在堆疊中構造了UI執行緒對象,可以利用默認的ExitInstance()自動將它刪除。

相關詞條

熱門詞條

聯絡我們