在前面我們研究了使用afx_manage_state(
afxgetstaticmodulestate())進行
dll間的資源切換,以及工作執行緒中建立
windows
訊息迴圈的原理,以為就可以搞定一切類似問題了
…但是請看以下**
dword ctestmfcdlg::threadfunc(pvoid yy)
void ctestmfcdlg::onok()
在vc++6.0
上編譯執行出現以下
assert。
void cwnd::assertvalid() const
return pstate->m_pmaphwnd;
看來這個
hash
表跟afxgetmodulethreadstate
()有關,繼續
afx_module_thread_state* afxapi afxgetmodulethreadstate()
afx_module_state* afxapi afxgetmodulestate()
else
assert(presult != null);
return presult;}那麼
_afxthreadstate是什麼呢?
extern_thread_local(_afx_thread_state, _afxthreadstate)
class _afx_thread_state : public cnotrackobject
afx_inline operator type*()
afx_inline type* operator->()
static cnotrackobject* afxapi createobject()
可以看出來了,
_afxthreadstate是乙個全域性的物件。通過該物件可以獲得_afx_thread_state物件,後者是執行緒相關的。cthreadlocalobject的**不再分析,大概就是檢查當前的執行緒私有資料,如果有則返回,否則建立新的物件(即_afx_thread_state)。
繼續看afxgetmodulestate(),大致的意思是獲取與當前執行緒相關聯的afx_module_state物件,如果沒有則獲取該程序的預設afx_module_state物件。
process_local(_afx_base_module_state, _afxbasemodulestate)
class _afx_base_module_state : public afx_module_state
#define process_local(class_name, ident_name) /
afx_datadef cprocesslocalident_name;
#define extern_process_local(class_name, ident_name) /
extern afx_data process_local(class_name, ident_name)
繼續看afxgetmodulethreadstate
(),在獲得了afx_module_state物件之後,訪問其m_thread成員。這又是乙個執行緒相關的資料,可以獲得afx_module_state在不同執行緒中的私有資料。
// afx_module_state (global data for a module)
class afx_module_state : public cnotrackobject
return true;
bool cwinthread::pretranslatemessage(msg* pmsg)
cwnd* cwinthread::getmainwnd()
很顯然是想獲取當前執行緒關聯的
module
對應的cwinthread
對應的主視窗
/啟用視窗。
因為主線程和工作執行緒都沒有做
module
的切換工作,_afxthreadstate->m_pmodulestate都為空,所以兩個執行緒執行afxgetmodulestate()的結果總是返回程序預設的afx_module_state物件,即_afxbasemodulestate。所以afxgetthread()(
),後者的m_pmainwnd成員指向的就是ctestmfcdlg物件。
在呼叫ctestmfcdlg的pretranslatemessage函式的時候,其內部進行了如下檢查
cframewnd* cwnd::gettoplevelframe() const
因為afxbeginthread
內部會自動做一些處理,所以也沒有問題。 3.
另外我們還發現,如果只有乙個視窗,即沒有ctestmfcdlg視窗存在的情況下,
caboutdlg
是可以正常顯示的,因為不涉及跨執行緒訪問
mfc物件的情況。這就是為什麼我們經常在非
mfc的
com元件裡可以多執行緒使用單個
mfc視窗的原因。
mfc並不是只能在主線程裡使用,只是不能跨執行緒傳遞物件而以。 4.
有沒有可能使用
createthread()
afxbeginthread
內部可能也是呼叫
createthread
這個windows
的api
,既然它能,我們肯定也能,只是**的多少而已。有沒有可能像前面的文章對
dll輸出函式的資源切換那麼簡單,就用afx_manage_state(
afxgetstaticmodulestate())?
我們試著加上afx_manage_state(afxgetstaticmodulestate()),結果是
_afxwin_inline hinstance afxapi afxgetresourcehandle()
static _afx_dll_module_state afxmodulestate;
而原本afxgetmodulestate()返回的是_afxbasemodulestate,兩者是不同的。現在連資源都裝載不了,更別說下面的訊息迴圈了!而前面我們已經能夠裝載資源了,所以新增的這句話簡直是火上澆油,毫無益處!
現在我們就納悶了,現在的情況跟以前我們遇到的顯示
dll裡的視窗有什麼不同麼?為什麼之前可以這麼做,而現在不可以?看起來兩者完全一樣嘛!仔細想一想,原來以前的情況是只有乙個執行緒,跨越兩個
dll,所以需要切換的只是
modulestate
。現在是在同乙個
dll/exe
裡,需要跨越的是兩個執行緒!哦,這樣看來,應該要切換的是
modulethreadstate
,讓兩個執行緒使用同乙個
modulethreadstate
。因此,需要執行緒的建立者把自己的
modulethreadstate
傳給被建立執行緒,並進行相關的替換
--你可以檢視afxbeginthread
/cwinthread的實現**,而以下是我的簡單實現。
dword ctestmfcdlg::threadfunc(pvoid ref_mts)
void ctestmfcdlg::onok()
因為執行緒結束後,執行緒的私有資料會被刪除,所以需要首先儲存原有的位址,在最後恢復再刪除,否則刪除的將是引用的資料。
如何在工作執行緒中建立視窗?
在前面我們研究了使用afx manage state afxgetstaticmodulestate 進行 dll間的資源切換,以及工作執行緒中建立 windows 訊息迴圈的原理,以為就可以搞定一切類似問題了 但是請看以下 dword ctestmfcdlg threadfunc pvoid yy...
如何在工作執行緒中建立視窗?
在前面我們研究了使用afx manage state afxgetstaticmodulestate 進行 dll間的資源切換,以及工作執行緒中建立 windows 訊息迴圈的原理,以為就可以搞定一切類似問題了 但是請看以下 dword ctestmfcdlg threadfunc pvoid yy...
C 如何在類中建立執行緒
一般我們在啟執行緒時,都是把執行緒函式寫成全域性函式來使用,但是如果要把執行緒操作寫成類,執行緒函式放在類裡面在c 編譯會不通過。在c 類中建立執行緒會有報錯 下面以乙個簡單的類進行舉例 external.件 ifndef radio external h define radio external...