MFC 多執行緒程式設計

2021-08-08 16:14:31 字數 3751 閱讀 8310

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...