Simple Thread Example






1.56/5 (9 votes)
This program shows how to use threads in your application using MFC.
Introduction
This application explains how to use a thread in a dialog based MFC application. It demonstrates how threads work independently from each other and how to control thread execution.
Background
Suppose you have to write an application in which two actions are running simultaneously. In such a case, threads is one of the options.
Using the code
Now, we will make two threads which display 1 to 100 count in two edit boxes of a dialog box. Each thread is started by its own button. Each time, a button flag runs or stops thread execution. Each thread has its own thread data structure.
Press the Run button to run a thread and the Stop button to stop a thread.
// StopClockDlg.cpp : implementation file
//
#include "stdafx.h"
#include "StopClock.h"
#include "StopClockDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
typedef struct tagThreadData{
CStopClockDlg* pObjDlg;
INT* pnEditBoxValue;
UINT nEditId;
}THREADDATA;
THREADDATA* TD1 = new THREADDATA;
THREADDATA* TD2 = new THREADDATA;
BOOL bRunT1 = FALSE;
BOOL bRunT2 = FALSE;
BOOL bFirstTimeT1 = TRUE;
BOOL bFirstTimeT2 = TRUE;
//Definition of the Worker Threads functions
//-----------------------------------------------------------//
UINT WorkerThreadFunction(LPVOID pParam)
{
THREADDATA* pData = (THREADDATA*) pParam;
INT* pnEditBoxValue = pData->pnEditBoxValue;
UINT nEid = pData->nEditId;
CStopClockDlg* pDlg = pData->pObjDlg;
while(1){
if(*pnEditBoxValue < 100){
(*pnEditBoxValue) ++;
}else{
*pnEditBoxValue = 1;
}
pDlg->SetDlgItemInt(nEid, *pnEditBoxValue);
::Sleep(50);
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CStopClockDlg dialog
CStopClockDlg::CStopClockDlg(CWnd* pParent /*=NULL*/)
: CDialog(CStopClockDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CStopClockDlg)
m_E1 = 1;
m_E2 = 1;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CStopClockDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CStopClockDlg)
DDX_Text(pDX, IDC_EDIT1, m_E1);
DDX_Text(pDX, IDC_EDIT2, m_E2);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CStopClockDlg, CDialog)
//{{AFX_MSG_MAP(CStopClockDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CStopClockDlg message handlers
BOOL CStopClockDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 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
SetDlgItemText(IDC_BUTTON1, "Run");
SetDlgItemText(IDC_BUTTON2, "Run");
TD1->pObjDlg = this;
TD1->pnEditBoxValue = &m_E1;
TD1->nEditId = IDC_EDIT1;
TD2->pObjDlg = this;
TD2->pnEditBoxValue = &m_E2;
TD2->nEditId = IDC_EDIT2;
return TRUE; // return TRUE unless you set the focus to a control
}
void CStopClockDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 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 CStopClockDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (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
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CStopClockDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CStopClockDlg::OnButton1()
{
// TODO: Add your control notification handler code here
bRunT1 = !bRunT1;
if(bRunT1){
SetDlgItemText(IDC_BUTTON1, "PAUSE");
}else{
SetDlgItemText(IDC_BUTTON1, "RUN");
}
if(bFirstTimeT1){
//The Creation and running of Threads Starts
theApp.m_pThreads [0]=AfxBeginThread(WorkerThreadFunction,TD1);
bFirstTimeT1 = FALSE;
}
if(bRunT1){
theApp.m_pThreads[0]->ResumeThread();
}else{
theApp.m_pThreads[0]->SuspendThread();
}
}
void CStopClockDlg::OnButton2()
{
// TODO: Add your control notification handler code here
bRunT2 = !bRunT2;
if(bRunT2){
SetDlgItemText(IDC_BUTTON2, "PAUSE");
}else{
SetDlgItemText(IDC_BUTTON2, "RUN");
}
if(bFirstTimeT2){
//The Creation and running of Threads Starts
theApp.m_pThreads [1]=AfxBeginThread(WorkerThreadFunction,TD2);
bFirstTimeT2 = FALSE;
}
if(bRunT2 ){
theApp.m_pThreads[1]->ResumeThread();
}else{
theApp.m_pThreads[1]->SuspendThread();
}
}
Please reply to me if you have any difficulties with this code. Thank you...