无涯教程-MFC - 多线程

92 阅读3分钟

Microsoft基础类(MFC)库提供对多线程应用程序的支持,当您启动记事本时,操作系统将创建一个进程并开始执行该进程的主线程。当该线程终止时,该过程也终止。

您可以根据需要在应用程序中创建其他线程, MFC应用程序中的所有线程均由CWinThread对象表示,在大多数情况下,您甚至不必显式创建这些对象,而是调用框架帮助器函数AfxBeginThread,该函数为您创建CWinThread对象。

让无涯教程通过创建一个新的基于MFC对话框的应用程序来研究一个简单的示例。

步骤1 - 将静态控件的标题和ID分别更改为单击"Start Thread"按钮和 IDC_STATIC_TEXT 。

步骤2 - 拖动两个按钮,并为这些按钮添加click事件处理程序。

Start Thread Button

步骤3 - 为Static text 控件添加控件变量。

步骤4 - 现在在CMFCMultithreadingDlg.cpp文件的开头添加以下三个全局变量。

int currValue;
int maxValue;
BOOL stopNow;

步骤5 - 在CMFCMultithreadingDlg类中添加WM_TIMER消息。

这是OnTimer()的实现

void CMFCMultithreadingDlg::OnTimer(UINT_PTR nIDEvent) {
   //TODO: Add your message handler code here and/or call default
   CString sStatusMsg;
   sStatusMsg.Format(L"Running: %d", currValue);
   m_ctrlStatus.SetWindowText(sStatusMsg);

CDialogEx::OnTimer(nIDEvent); }

步骤6 - 现在在CMFCMultithreadingDlg类的AfxBeginThread中添加一个示例函数。

UINT MyThreadProc(LPVOID Param) {
   while (!stopNow && (currValue < maxValue)) {
      currValue++;
      Sleep(50);     //would do some work here
   }

return TRUE; }

步骤7 - 这是"Start thread"按钮的事件处理程序的实现,它将启动线程。

void CMFCMultithreadingDlg::OnBnClickedButtonStart() {
   //TODO: Add your control notification handler code here
   currValue = 0;
   maxValue = 5000;
   stopNow = 0;
   m_ctrlStatus.SetWindowText(L"Starting...");
   SetTimer(1234, 333, 0); //每秒 3 次

AfxBeginThread(MyThreadProc, 0); //<<== START THE THREAD }

步骤8 - 这是Stop Thread按钮的事件处理程序的实现,它将停止线程。

void CMFCMultithreadingDlg::OnBnClickedButtonStop() {

//TODO: Add your control notification handler code here stopNow = TRUE; KillTimer(1234); m_ctrlStatus.SetWindowText(L"Stopped"); }

步骤9 - 这是完整的源文件。

//MFCMultithreadingDlg.cpp : implementation file
//

#include "stdafx.h" #include "MFCMultithreading.h" #include "MFCMultithreadingDlg.h" #include "afxdialogex.h"

#ifdef _DEBUG #define new DEBUG_NEW #endif

//CMFCMultithreadingDlg dialog

int currValue; int maxValue; BOOL stopNow;

CMFCMultithreadingDlg::CMFCMultithreadingDlg(CWnd pParent /=NULL*/) : CDialogEx(IDD_MFCMULTITHREADING_DIALOG, pParent) { m_hIcon = AfxGetApp() -> LoadIcon(IDR_MAINFRAME); } void CMFCMultithreadingDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_STATIC_TEXT, m_ctrlStatus); }

BEGIN_MESSAGE_MAP(CMFCMultithreadingDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON_START, &CMFCMultithreadingDlg::OnBnClickedButtonStart) ON_WM_TIMER() ON_BN_CLICKED(IDC_BUTTON_STOP, &CMFCMultithreadingDlg::OnBnClickedButtonStop) END_MESSAGE_MAP()

//CMFCMultithreadingDlg message handlers

BOOL CMFCMultithreadingDlg::OnInitDialog() { CDialogEx::OnInitDialog();

//设置此对话框的图标。该框架会自动执行此操作当应用程序的主窗口不是对话框时 SetIcon(m_hIcon, TRUE); //Set big icon SetIcon(m_hIcon, FALSE); //Set small icon

//TODO: Add extra initialization here

return TRUE; //除非您将焦点设置为控件,否则返回 TRUE }

//除非您将焦点设置为控件,否则返回 TRUE绘制图标。对于使用文档/视图模型的 MFC 应用程序, //这是由框架自动为您完成的。

void CMFCMultithreadingDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); //device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

  </span><span class="com">//Center icon in client rectangle</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> cxIcon </span><span class="pun">=</span><span class="pln"> </span><span class="typ">GetSystemMetrics</span><span class="pun">(</span><span class="pln">SM_CXICON</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> cyIcon </span><span class="pun">=</span><span class="pln"> </span><span class="typ">GetSystemMetrics</span><span class="pun">(</span><span class="pln">SM_CYICON</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">CRect</span><span class="pln"> rect</span><span class="pun">;</span><span class="pln">
  </span><span class="typ">GetClientRect</span><span class="pun">(&amp;</span><span class="pln">rect</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">rect</span><span class="pun">.</span><span class="typ">Width</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> cxIcon </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)/</span><span class="lit">2</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">rect</span><span class="pun">.</span><span class="typ">Height</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> cyIcon </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)/</span><span class="lit">2</span><span class="pun">;</span><span class="pln">

  </span><span class="com">//Draw the icon</span><span class="pln">
  dc</span><span class="pun">.</span><span class="typ">DrawIcon</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> m_hIcon</span><span class="pun">);</span><span class="pln">

}else { CDialogEx::OnPaint(); } } //系统调用该函数获取用户拖动时要显示的光标 //最小化的窗口。 HCURSOR CMFCMultithreadingDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); }

UINT /CThreadDlg::/MyThreadProc(LPVOID Param) //Sample function for using in AfxBeginThread { while (!stopNow && (currValue < maxValue)) { currValue++; Sleep(50); //would do some work here } return TRUE; } void CMFCMultithreadingDlg::OnBnClickedButtonStart() { //TODO: Add your control notification handler code here currValue = 0; maxValue = 5000; stopNow = 0; m_ctrlStatus.SetWindowText(L"Starting..."); SetTimer(1234, 333, 0); //3 times per second

AfxBeginThread(MyThreadProc, 0); //<<== START THE THREAD }

void CMFCMultithreadingDlg::OnTimer(UINT_PTR nIDEvent) { //TODO: Add your message handler code here and/or call default CString sStatusMsg; sStatusMsg.Format(L"Running: %d", currValue); m_ctrlStatus.SetWindowText(sStatusMsg);

CDialogEx::OnTimer(nIDEvent); }

void CMFCMultithreadingDlg::OnBnClickedButtonStop() { //TODO: Add your control notification handler code here stopNow = TRUE; KillTimer(1234); m_ctrlStatus.SetWindowText(L"Stopped"); }

步骤10 - 编译并执行上述代码后,您将看到以下输出。

Multithreading

步骤11 - 现在,单击"Start Thread"按钮。

Start Thread

步骤12 - 单击"Stop Thread"按钮。它将停止线程。

Stop Thread

参考链接

www.learnfk.com/mfc/mfc-mul…