MFC架構之CWinThread類

2021-06-26 17:06:56 字數 4180 閱讀 7088

我們知道,windows以事件驅動方式工作,每個win32應用程式都至少包含乙個訊息佇列和乙個訊息幫浦。訊息佇列建立在作業系統提供的記憶體保留區中,訊息幫浦不斷搜尋訊息佇列,將取得的訊息分發給應用程式的各個部分進行處理,這個過程叫做訊息迴圈。基本訊息迴圈如下:

[cpp]view plain

copy

while(getmessage(&msg,0,0,0))  

下面介紹幾個實用的cwinthread類成員函式。

1.虛函式initinstance

windows允許同時執行乙個應用程式的多個備份,又稱為執行乙個程式的多個例項。 initinstance就是「初始化例項」的意思,可見,它是在例項建立時首先被呼叫的。應用程式總要過載這個虛函式,進行系統設定,建立執行環境。例如,主視窗一定要在initinstance()中建立,因為該函式退出後就進入該執行緒的訊息迴圈。

2.虛函式run

該函式提供ui執行緒的訊息迴圈,即反覆地提取訊息,分發訊息,直到收到wm_quit退出迴圈,執行緒隨即結束。在迴圈中,如果當前沒有收到訊息,則呼叫空閒訊息處理程式onidle() 。以下是該函式的完整定義。

[cpp]view plain

copy

virtualintcwinthread::run()  

//空閒處理迴圈結束,進入訊息幫浦迴圈

do

}while(::peekmessage(&m_msgcur, null, null, null, pm_noremove));  

}  assert(false); //不可能執行的語句

}  /*------------- 訊息幫浦函式pumpmessage() ----------------*/

//省略了除錯資訊的輸出功能

boolcwinthread::pumpmessage()  

//處理訊息,但不處理wm_kickidle

if(m_msgcur.message != wm_kickidle && !pretranslatemessage(&m_msgcur))  

returntrue;  

}  閱讀pumpmessage**可知,訊息幫浦並不處理wm_kickidle訊息,收到該訊息後,直接返回。其實,wm_kickidle訊息被用來刺激空閒處理的執行,它作為乙個空訊息促使::getmessage()返回。雖然run()是虛函式,但很少被過載。

3.虛函式exitinstance

與initinstance()相反,該函式是在退出訊息迴圈時執行,一般被框架呼叫,做最後的清理工作。但如果呼叫initinstance()失敗,exitinstance()也會被呼叫。可以過載exitinstance(),為執行緒做相關的清理工作。不要在除過載的run()函式外的地方呼叫它。如果將cwinthread成員變數m_bautodelete設為 true,cwinthread::exitinstance()會刪除當前的cwinthread物件。所以,如果在堆疊中構造了ui執行緒物件,可以利用預設的exitinstance()自動將它刪除。

4.虛函式virtual bool pretranslatemessage(msg *pmsg );

在訊息在translatemessage和dispatchmessage之前過濾訊息。

5.虛函式virtual bool onidle(long lcount);

在空閒時處理。

cwinthread的使用

常見的啟動執行緒函式有三個:  

createthread(),   _beginthread(以及_beginthreadex()),afxbeginthread()  

1和2是sdk函式,3是mfc函式  

至於啟動的是工作者執行緒還是ui執行緒,是由函式3的引數來決定的 ;

乙個例子:

[cpp]view plain

copy

classcuithread :publiccwinthread  

}afx_virtual

// implementation

protected:  

virtual~cuithread();  

// generated message map functions

//}afx_msg

declare_message_map()  

};  

//過載函式initinstance()和exitinstance()

boolcuithread::initinstance()  

//建立新的使用者介面執行緒 

voidcuithreaddlg::onbutton1()  

請注意以下兩點:

1.在uithreaddlg.cpp的開頭加入語句: #include "uithread.h"

2.把uithread.h中類cuithread()的建構函式的特性由 protected 改為 public。

使用者介面執行緒的執行次序與應用程式主線程相同,首先呼叫使用者介面執行緒類的initinstance()函式,如果返回true,繼續呼叫執行緒的 run()函式,該函式的作用是執行乙個標準的訊息迴圈,並且當收到wm_quit訊息後中斷,在訊息迴圈過程中,run()函式檢測到執行緒空閒時(沒有訊息),也將呼叫onidle()函式,最後run()函式返回,mfc呼叫exitinstance()函式清理資源。

你可以建立乙個沒有介面而有訊息迴圈的執行緒,例如:你可以從cwinthread派生乙個新類,在initinstance函式中完成某項任務並返回false,這表示僅執行initinstance函式中的任務而不執行訊息迴圈,你可以通過這種方法,完成乙個工作者執行緒的功能。

另乙個例子:

[cpp]view plain

copy

//.h 檔案

#define wm_test    wm_user + 1

classctestthread :publiccwinthread  

;  //.cpp 檔案

#include "stdafx.h"

#include "testthread.h"

implement_dyncreate(ctestthread, cwinthread)  

ctestthread::ctestthread()  

ctestthread::~ctestthread()  

begin_message_map(ctestthread, cwinthread)  

on_thread_message(wm_test,ontest)  

end_message_map()  

boolctestthread::initinstance()  

intctestthread::exitinstance()  

voidctestthread::ontest(wparamwparam,lparamlparam)  

//呼叫的地方

cwinthread* m_pthrd;  

//啟動

m_pthrd = afxbeginthread(runtime_class(ctestthread));  

// 需要執行執行緒中的操作時

m_pthrd->postthreadmessage(wm_test,null,null);  

// 結束執行緒

handlehp=m_pthrd->m_hthread;  

if(hp)   

closehandle(hp);  

}  fr:

MFC架構之CWinApp類

1.成員變數 2.常用全域性函式 3.可過載函式 4.命令處理 onfilenew 實現id file new命令 onfileopen 實現id file new命令 onfileprintsetup 實現id file print setup命令 oncontexthelp 處理應用程式內的sh...

MFC架構之CWinApp類

1.成員變數 2.常用全域性函式 3.可過載函式 4.命令處理 onfilenew 實現id file new命令 onfileopen 實現id file new命令 onfileprintsetup 實現id file print setup命令 oncontexthelp 處理應用程式內的sh...

MFC單文件程式架構解析

首先我們了解到的是 圖 一 圖 二 csingledoctemplate pdoctemplate pdoctemplate new csingledoctemplate idr mainframe,runtime class cmainframe main sdi frame windon 這裡體...