Click here to Skip to main content
15,886,362 members
Articles / Desktop Programming / MFC

Simple Thread Example

Rate me:
Please Sign up or sign in to vote.
1.56/5 (9 votes)
5 Jul 2009CPOL 39.6K   1.3K   12   2
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.

C++
// 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...

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
India India
Hi,
I am working...

Comments and Discussions

 
QuestionNeed Explanation Pin
Member 1202989427-Feb-21 4:15
Member 1202989427-Feb-21 4:15 
GeneralMy vote of 1 Pin
bolivar1236-Jul-09 7:10
bolivar1236-Jul-09 7:10 
Where's the article? Need more content. Perhaps you should add more information about:

Why would a person want/need to do multiple threads?

What about thread synchronicity/thread safety?

I might have voted higher if you had a little more detail.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.