複製鏈接
請複製以下鏈接發送給好友

CWinThread

鎖定
MFC類。CWinThread類是MFC用來封裝線程的,包括UI線程和工作者線程。因此每個MFC程序至少使用一個CWinThread派生類。被MFC程序員熟知的CWinApp應用類就從這裏派生。
中文名
CWinThread
外文名
CWinThread
釋    義
MFC用來封裝的線程

目錄

CWinThread説明

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

CWinThread成員函數

下面介紹幾個實用的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()自動將它刪除。