The Microsoft Foundation Class (MFC) library provides support for multithreaded applications. A thread is a path of execution within a process. When you start Notepad, the operating system creates a process and begins executing the primary thread of that process. When this thread terminates, so does the process.
You can create additional threads in your application if you want. All threads in MFC applications are represented by CWinThread objects. In most situations, you do not even have to explicitly create these objects; instead call the framework helper function AfxBeginThread, which creates the CWinThread object for you.
Let us look into a simple example by creating a new MFC dialog based application.
Step 1 − Change the Caption and ID of Static control to Click on Start Thread button and IDC_STATIC_TEXT respectively.
Step 2 − Drag two buttons and add click event handlers for these buttons.
Step 3 − Add control variable for static text control.
Step 4 − Now add the following three global variables at the start of CMFCMultithreadingDlg.cpp file.
int currValue; int maxValue; BOOL stopNow;
Step 5 − Add the WM_TIMER message in CMFCMultithreadingDlg class.
Here is the implementation of 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); }
Step 6 − Now add a sample function for using in AfxBeginThread in CMFCMultithreadingDlg class.
UINT MyThreadProc(LPVOID Param) { while (!stopNow && (currValue < maxValue)) { currValue++; Sleep(50); // would do some work here } return TRUE; }
Step 7 − Here is the implementation of event handler for Start Thread button, which will start the 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 times per second AfxBeginThread(MyThreadProc, 0); // <<== START THE THREAD }
Step 8 − Here is the implementation of event handler for Stop Thread button, which will stop the thread.
void CMFCMultithreadingDlg::OnBnClickedButtonStop() { // TODO: Add your control notification handler code here stopNow = TRUE; KillTimer(1234); m_ctrlStatus.SetWindowText(L"Stopped"); }
Step 9 − Here is the complete source file.
// 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(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMFCMultithreadingDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); }else { CDialogEx::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. 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"); }
Step 10 − When the above code is compiled and executed, you will see the following output.
Step 11 − Now click on Start Thread button.
Step 12 − Click the Stop Thread button. It will stop the thread.