如何在工作執行緒中建立視窗?

2021-04-12 13:53:45 字數 3647 閱讀 7447

在前面我們研究了使用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...