主執行緒(UI)與工作者執行緒(背景運算)頻繁交換資料:主執行緒下發任務參數、工作者執行緒回報進度/結果。MFC 提供兩種主要通訊方式。
volatile 關鍵字,防止編譯器優化導致讀取舊值利用 Windows 訊息機制:發送端 PostThreadMessage,接收端需有訊息迴路。工作者執行緒若衍生自 CWinThread 並覆寫 InitInstance() 返回 TRUE,即擁有訊息迴路。
場景:主執行緒選擇加數上限 (10/50/100) → 發送 WM_CALCULATE → 計算執行緒累加 → 發送 WM_DISPLAY 回主執行緒顯示結果。
#define WM_CALCULATE (WM_USER + 1)
#define WM_DISPLAY (WM_USER + 2)
class CMultiThread7Dlg : public CDialog {
// ...
protected:
int m_nAddend; // 加數上限
CCalculateThread* m_pCalcThread;
afx_msg LRESULT OnDisplay(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
};
// 訊息映射
BEGIN_MESSAGE_MAP(CMultiThread7Dlg, CDialog)
ON_MESSAGE(WM_DISPLAY, OnDisplay)
END_MESSAGE_MAP()
// 處理計算結果顯示
LRESULT CMultiThread7Dlg::OnDisplay(WPARAM wParam, LPARAM) {
SetDlgItemInt(IDC_STATUS, (int)wParam, FALSE);
return 0;
}
// 「求和」按鈕:啟動執行緒並發送參數
void CMultiThread7Dlg::OnSum() {
m_pCalcThread = (CCalculateThread*)AfxBeginThread(RUNTIME_CLASS(CCalculateThread));
Sleep(500); // 確保執行緒啟動完成
m_pCalcThread->PostThreadMessage(WM_CALCULATE, m_nAddend, 0);
}
class CCalculateThread : public CWinThread {
DECLARE_DYNCREATE(CCalculateThread)
protected:
afx_msg LONG OnCalculate(UINT wParam, LONG lParam);
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CCalculateThread, CWinThread)
ON_THREAD_MESSAGE(WM_CALCULATE, OnCalculate) // 注意:ON_THREAD_MESSAGE
END_MESSAGE_MAP()
LONG CCalculateThread::OnCalculate(UINT wParam, LONG) {
int sum = 0;
for (int i = 0; i <= (int)wParam; i++) sum += i;
Sleep(500); // 模擬耗時運算
// 向主視窗發送結果 (需包含主對話框標頭檔)
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WM_DISPLAY, sum, 0);
return 0;
}
| 特性 | 主執行緒 (CDialog) | 工作者執行緒 (CWinThread) |
|---|---|---|
| 訊息映射巨集 | ON_MESSAGE | ON_THREAD_MESSAGE |
| 發送訊息 API | PostMessage | PostThreadMessage |
| 接收端需有訊息迴路 | 是 (預設) | 是 (覆寫 InitInstance 回傳 TRUE) |
WPARAM/LPARAM 僅能傳 32/64 位元整數LPARAM,接收端處理完負責釋放自訂訊息機制實現執行緒間非阻塞、鬆耦合通訊,是 MFC 多執行緒開發的核心模式。搭配 CWinThread 訊息迴路,可構建清晰的生產者-消費者、主從協作架構。