mfc中有兩類執行緒 , 分別稱之為工作者執行緒和使用者介面執行緒 ;
二者的主要區別在於工作者執行緒沒有訊息迴圈 , 而使用者介面執行緒有自己的訊息佇列和訊息迴圈;
但對於 win32 的 api 程式設計而言 , 這兩種執行緒是沒有區別的 , 它們都只需執行緒的啟動位址即可啟動執行緒來執行任務 ;
在mfc中 , 一般用全域性函式afxbeginthread()
來建立並初始化乙個執行緒的執行 , 該函式有兩種過載形式 , 分別用於建立工作者執行緒和使用者介面執行緒 (ui 執行緒) ; 兩種過載函式原型和引數分別說明如下 :
工作者執行緒
cwinthread* afxbeginthread(afx_threadproc pfnthreadproc,
lpvoid pparam,
npriority=thread_priority_normal,
uint nstacksize=0,
dword dwcreateflags=0,
lpsecurity_attributes lpsecurityattrs=null);
其中各引數說明如下 :
pfnthreadproc : 指向工作者執行緒的執行函式的指標 , 執行緒函式原型必須宣告如 :uint executingfunction(lpvoid pparam);
, 請注意 ,executingfunction()
應返回乙個 uint 型別的值 , 用以指明該函式結束的原因 , 一般情況下 , 返回 0 表明執行成功 ;
pparam : 傳遞給執行緒函式的乙個 32 位引數 , 執行函式將用某種方式解釋該值 , 它可以是數值 , 或是指向乙個結構的指標 , 甚至可以被忽略 ;
npriority : 執行緒的優先順序 , 如果為 0 , 則執行緒與其父執行緒具有相同的優先順序 ;
nstacksize : 執行緒為自己分配堆疊的大小 , 其單位為位元組 ; 如果 nstacksize 被設為 0 , 則執行緒的堆疊被設定成與父執行緒堆疊相同大小 ;
dwcreateflags : 如果為 0 , 則執行緒在建立後立刻開始執行 ; 如果為create_suspend
, 則執行緒在建立後立刻被掛起 ;
lpsecurityattrs : 執行緒的安全屬性指標 , 一般為 null ;
使用者介面執行緒
cwinthread* afxbeginthread(cruntimeclass* pthreadclass,
int npriority=thread_priority_normal,
uint nstacksize=0,
dword dwcreateflags=0,
lpsecurity_attributes lpsecurityattrs=null);
其中各引數說明如下 :
pthreadclass : 指向cwinthread
的乙個匯出類的執行時類物件的指標 , 該匯出類定義了被建立的使用者介面執行緒的啟動 , 退出等 ;
其它引數的意義同工作者執行緒類似 ;
使用函式的這個原型生成的執行緒也有訊息機制 , 在以後的例子中我們將發現同主線程的機制幾乎一樣 ;
cwinthread 類
cwinthread 類的資料成員簡要說明如下 :
`m_hthread` : 當前執行緒的控制代碼 ;
`m_nthreadid` : 當前執行緒的id ;
`m_pmainwnd` : 指向應用程式主視窗的指標 ;
cwinthread 類的常用函式簡要說明如下 :
bool cwinthread::createthread(dword dwcreateflags=0,
uint nstacksize=0,
lpsecurity_attributes lpsecurityattrs=null);
該函式中的 dwcreateflags , nstacksize , lpsecurityattrs 引數和 api 函式createthread
中的對應引數有相同含義 , 該函式執行成功 , 返回非 0 值 , 否則返回 0 ;
一般情況下 , 呼叫afxbeginthread();
來一次性地建立並啟動乙個執行緒 , 但是也可以通過兩步法來建立執行緒 : 首先建立 cwinthread 類的乙個物件 , 然後呼叫該物件的成員函式createthread();
來啟動該執行緒 ;
virtual bool cwinthread::initinstance();
過載該函式以控制使用者介面執行緒例項的初始化 ; 初始化成功則返回非 0 值 , 否則返回 0 ; 使用者介面執行緒經常過載該函式 , 工作者執行緒一般不使用該函式函式 ;
virtual int cwinthread::exitinstance();
mfc 建立工作者執行緒**如下 :
新建乙個 mfc 對話方塊專案 , 在對話方塊標頭檔案定義乙個工作者執行緒函式 , 如下 :
static uint workerthreadfunc(lpvoid lpparam);
原始檔實現如下 (這裡讓工作者執行緒等待一秒左右時間模擬資料處理) :
uint cmfcworkerthreaddlg::workerthreadfunc(lpvoid lpparam)
return 0;
}
建立工作者執行緒**如下 :
void cmfcworkerthreaddlg::onbnclickedbuttonstart()
mfc 建立ui執行緒**如下 :
建立 cwinthread 的派生類 cuithread :
// uithread.h 檔案
#pragma once
class cuithread : public cwinthread
;
過載函式initinstance();
和exitinstance();
:
// uithread.cpp 檔案
#include "stdafx.h"
#include "uithread.h"
implement_dyncreate(cuithread, cwinthread)
cuithread::cuithread()
cuithread::~cuithread()
bool cuithread::initinstance()
int cuithread::exitinstance()
begin_message_map(cuithread, cwinthread)
end_message_map()
在主對話方塊啟動 ui 執行緒 :
void cmaindlg::onbnclickedstartui()
作者 github : tojohnonly , 部落格 : enskdecode
MFC多執行緒程式設計
具體來說是 在mfc中呼叫attach的時候 有個巨集叫assert valid 這個方法不允許訪問非本執行緒建立的繼承於。在cwnd函式裡面有乙個valid 的靜態方法,檢測當前執行緒的mfc物件指標,是否在當前執行緒的map中 下面就是這個模組中線程狀態結構體 afx module thread...
MFC多執行緒程式設計總結
mfc多執行緒程式設計總結 mfc中,在多個執行緒之間通話 資料共享與同步的方法有 1.全域性變數。全域性變數需要用volatile宣告以防止使用暫存器導致出錯。也可以使用interlockedincrement在阻塞其它執行緒的條件下修改單個全域性變數。這是一種簡單的在同一程序中線程之間通話與資料...
MFC多執行緒程式設計總結
在mfc程式中使用afxbeginthread函式來建立乙個執行緒,該函式因引數不同而具有兩種過載函式,分別對應工作者執行緒和使用者介面 ui 執行緒。一 工作執行緒 1 建立執行緒mfc api函式 cwinthread afxbeginthread afx threadproc pfnthrea...