MFC多執行緒程式設計總結

2021-07-24 18:17:55 字數 4717 閱讀 9802

在mfc程式中使用afxbeginthread函式來建立乙個執行緒,該函式因引數不同而具有兩種過載函式,分別對應工作者執行緒和使用者介面(ui)執行緒。

一、工作執行緒

1、建立執行緒mfc api函式

cwinthread *afxbeginthread(

afx_threadproc pfnthreadproc, //執行緒函式

lpvoid pparam, //傳遞給控制函式的引數

int npriority = thread_priority_normal, //執行緒的優先順序

uint nstacksize = 0, //執行緒的堆疊大小

dword dwcreateflags = 0, //執行緒的建立標誌

lpsecurity_attributes lpsecurityattrs = null //執行緒的安全屬性);

2、執行緒工作函式

uint mfcthreadproc(lpvoid lpparam)

return 0; //返回0則表示執行緒正確退出執行緒

}3、使用例

m_pthread= afxbeginthread(newthreadtest,&wenli);

m_pthread ->m_bautodelete = true;

m_pthread ->resumethread();

m_bautodelete= true;

系統自己清理cwind物件,當然還包括closehandle(),exitinstance()等等一堆函式的呼叫。

m_bautodelete = false; 

自己在用完後呼叫delete()刪除建立執行緒的物件,否則會有記憶體洩漏問題。

二、ui執行緒

ui

執行緒 是由cwinthread

也是乙個ui執行緒,他是應用程式的主線程

,一般我們所說的ui

執行緒,是指除主線程

之外的介面

執行緒。1,建立使用者介面執行緒時,必須首先從cwinthread派生類。

2,使用declare_dyncreate 和 implement_dyncreate以建立類表。

3,使用vs提供的增加mfc類嚮導可以輕鬆完成類的新增工作,類新增後需要對其進行必要的修改。

需要重寫如下兩個成員函式。

//執行執行緒例項初始化,必須重寫

virtualbool initinstance();

//執行緒終止時執行清除,通常需要重寫

virtualint exitinstance(); // default will 'delete this'

4,建立執行緒函式原型。

cwinthread *afxbeginthread(

cruntimeclass *pthreadclass, //從cwinthread派生的類的 runtime_class

int npriority =thread_priority_normal,

uint nstacksize = 0,

dword dwcreateflags = 0,

lpsecurity_attributes lpsecurityattrs= null);

5,啟動執行緒

設定cwinthread

類的m_pmainwnd成員,否則這個執行緒不會隨著介面的關閉而退出。

cwinthread 

*ptread = afxbeginthread

(runtime_class(cmyuiclassname));

6,結束執行緒

①ui執行緒有訊息佇列,所以結束乙個ui執行緒最好的方法是發乙個wm_quit訊息給訊息佇列。

postquitmessage()

postthreadmessage()

但是發出訊息後最好等待看ui執行緒是否已經退出(很重要)。

if(pthread)   

}  ②普通的工作執行緒收到返回值既表示正確退出。

三、執行緒間的通訊

1、全域性變數方式。

2、控制項指標或其它全域性引數傳遞方式。

afxbeginthread(newthreadtest,&wenli);

3,訊息傳遞方式

a、工作執行緒可以使用:postthreadmessage()

訊息對映為on_thread_message而不是on_message

b、ui執行緒可以使用

非同步函式:postmessage()

同步函式:sendmessage()

c、使用方法

#define wm_threadmsg  wmuser+100

全域性函式::postthreadmessage(idthread

,wm_threadmsg,parm1, parm2);

或者使用類成員函式

m_pthread->postthreadmessage(wm_threadmsg,parm1, parm2); 

參考部落格:

四、執行緒同步

各個執行緒可以訪問程序中的公共變數,資源,所以使用多執行緒的過程中需要注意的問題是如何防止兩個或兩個以上的執行緒同時訪問同乙個資料,以免破壞資料的完整性。資料之間的相互制約包括

1、直接制約關係,即乙個執行緒的處理結果,為另乙個執行緒的輸入,因此執行緒之間直接制約著,這種關係可以稱之為同步關係

2、間接制約關係,即兩個執行緒需要訪問同一資源,該資源在同一時刻只能被乙個執行緒訪問,這種關係稱之為執行緒間對資源的互斥訪問,某種意義上說互斥是一種制約關係更小的同步。

a、 臨界區(ccriticalsection)

當多個執行緒訪問乙個獨占性共享資源時,可以使用臨界區物件。擁有臨界區的執行緒可以訪問被保護起來的資源或**段,其他執行緒若想訪問,則被掛起,直到擁有臨界區的執行緒放棄臨界區為止。具體應用方式:

1、 定義臨界區物件ccriticalsection g_criticalsection;

2、 在訪問共享資源(**或變數)之前,先獲得臨界區物件,g_criticalsection.lock();

3、 訪問共享資源後,則放棄臨界區物件,g_criticalsection.unlock();

b、 事件(cevent)

事件機制,則允許乙個執行緒在處理完乙個任務後,主動喚醒另外乙個執行緒執行任務。比如在某些網路應用程式中,乙個執行緒如a負責偵聽通訊埠,另外乙個執行緒b負責更新使用者資料,利用事件機制,則執行緒a可以通知執行緒b何時更新使用者資料。每個cevent物件可以有兩種狀態:有訊號狀態和無訊號狀態。cevent類物件有兩種型別:人工事件和自動事件。

自動事件物件,在被至少乙個執行緒釋放後自動返回到無訊號狀態;

人工事件物件,獲得訊號後,釋放可利用執行緒,但直到呼叫成員函式reset()才將其設定為無訊號狀態。在建立cevent物件時,預設建立的是自動事件。

1、cevent(boolbinitiallyown=false,

boolbmanualreset=false,

lpctstrlpszname=null,

lpsecurity_attributes lpsaattribute=null);

binitiallyown:指定事件物件初始化狀態,true為有訊號,false為無訊號;

bmanualreset:指定要建立的事件是屬於人工事件還是自動事件。true為人工事件,false為自動事件;

後兩個引數一般設為null,在此不作過多說明。

2、boolcevent::setevent();

將cevent 類物件的狀態設定為有訊號狀態。如果事件是人工事件,則cevent 類物件保持為有訊號狀態,直到呼叫成員函式resetevent()將 其重新設為無訊號狀態時為止。如果cevent 類物件為自動事件,則在setevent()將事件設定為有訊號狀態後,cevent 類物件由系統自動重置為無訊號狀態。

如果該函式執行成功,則返回非零值,否則返回零。

3、boolcevent::resetevent();

該函式將事件的狀態設定為無訊號狀態,並保持該狀態直至setevent()被呼叫時為止。由於自動事件是由系統自動重置,故自動事件不需要呼叫該函式。如果該函式執行成功,返回非零值,否則返回零。我們一般通過呼叫waitforsingleobject函式來監視事件狀態。  

c、 互斥量(cmutex)

互斥物件與臨界區物件很像.互斥物件與臨界區物件的不同在於:互斥物件可以在程序間使用,而臨界區物件只能在同一程序的各執行緒間使用。當然,互斥物件也可以用於同一程序的各個執行緒間,但是在這種情況下,使用臨界區會更節省系統資源,更有效率。

d、 訊號量(csemphore)

當需要乙個計數器來限制可以使用某個執行緒的數目時,可以使用「訊號量」物件。csemaphore 類的物件儲存了對當前訪問某一指定資源的執行緒的計數值,該計數值是當前還可以使用該資源的執行緒的數目。如果這個計數達到了零,則所有對這個csemaphore 類物件所控制的資源的訪問嘗試都被放入到乙個佇列中等待,直到超時或計數值不為零時為止。

MFC多執行緒程式設計總結

mfc多執行緒程式設計總結 mfc中,在多個執行緒之間通話 資料共享與同步的方法有 1.全域性變數。全域性變數需要用volatile宣告以防止使用暫存器導致出錯。也可以使用interlockedincrement在阻塞其它執行緒的條件下修改單個全域性變數。這是一種簡單的在同一程序中線程之間通話與資料...

MFC多執行緒程式設計

具體來說是 在mfc中呼叫attach的時候 有個巨集叫assert valid 這個方法不允許訪問非本執行緒建立的繼承於。在cwnd函式裡面有乙個valid 的靜態方法,檢測當前執行緒的mfc物件指標,是否在當前執行緒的map中 下面就是這個模組中線程狀態結構體 afx module thread...

MFC 多執行緒程式設計

mfc中有兩類執行緒 分別稱之為工作者執行緒和使用者介面執行緒 二者的主要區別在於工作者執行緒沒有訊息迴圈 而使用者介面執行緒有自己的訊息佇列和訊息迴圈 但對於 win32 的 api 程式設計而言 這兩種執行緒是沒有區別的 它們都只需執行緒的啟動位址即可啟動執行緒來執行任務 在mfc中 一般用全域...