界面如附件:(执行后列表框内没有信息)
界面如附件:(执行后列表框内没有信息)
代码如下:
#if !defined(AFX_EXAMPLETHREAD_H__0F85EFD4_065B_43C2_9406_073E240FB4FD__INCLUDED_)
#define AFX_EXAMPLETHREAD_H__0F85EFD4_065B_43C2_9406_073E240FB4FD__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ExampleThread.h : header file
//
#include "MultiThreadDlg.h"
/////////////////////////////////////////////////////////////////////////////
// CExampleThread thread
class CExampleThread : public CWinThread
{
    DECLARE_DYNCREATE(CExampleThread)
protected:
    CExampleThread();           // protected constructor used by dynamic creation
// Attributes
public:
    CMultiThreadDlg* m_pOwner;
    BOOL             m_bDone;
    void SetOwner(CMultiThreadDlg* pOwner)
    {
        m_pOwner=pOwner;
    };
// Operations
public:
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CExampleThread)
    public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();
    //}}AFX_VIRTUAL
// Implementation
protected:
    virtual ~CExampleThread();
    // Generated message map functions
    //{{AFX_MSG(CExampleThread)
        // NOTE - the ClassWizard will add and remove member functions here.
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
class CDisplayThread: public CExampleThread //新添加的类(CExampleThread是工程中的类)
{
    DECLARE_DYNCREATE(CDisplayThread)
public:
    virtual int Run();
    DECLARE_MESSAGE_MAP()
};
class CCounterThread: public CExampleThread //新添加的类(CExampleThread是工程中的类)
{
    DECLARE_DYNCREATE(CCounterThread)
public:
    virtual int Run();
    DECLARE_MESSAGE_MAP()
};
    //{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EXAMPLETHREAD_H__0F85EFD4_065B_43C2_9406_073E240FB4FD__INCLUDED_)
// ExampleThread.cpp : implementation file
//
#include "stdafx.h"
#include "MultiThread.h"
#include "ExampleThread.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "afxmt.h"
/////////////////////////////////////////////////////////////////////////////
// CExampleThread
IMPLEMENT_DYNCREATE(CExampleThread, CWinThread)
CExampleThread::CExampleThread()
{
    m_bDone=FALSE;
    m_pOwner=NULL;
}
CExampleThread::~CExampleThread()
{
}
BOOL CExampleThread::InitInstance()
{
    // TODO:  perform and per-thread initialization here
    return TRUE;
}
int CExampleThread::ExitInstance()
{
    // TODO:  perform any per-thread cleanup here
    return CWinThread::ExitInstance();
}
BEGIN_MESSAGE_MAP(CExampleThread, CWinThread)
    //{{AFX_MSG_MAP(CExampleThread)
        // NOTE - the ClassWizard will add and remove mapping macros here.
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CExampleThread message handlers
IMPLEMENT_DYNCREATE(CCounterThread, CExampleThread)
int CCounterThread::Run()
{
    BOOL fSyncChecked;
    unsigned int nNumber;
    if(m_pOwner==NULL)
        return -1;
    CSingleLock sLock(&(m_pOwner->m_mutex));
    while(!m_bDone)
    {
        fSyncChecked=m_pOwner->IsDlgButtonChecked(IDC_SYNCHRONIZE);
        if(fSyncChecked)
            sLock.Lock();
        _stscanf((LPCTSTR)m_pOwner->m_strNumber,_T("%d"),&nNumber);
        nNumber++;
        m_pOwner->m_strNumber.IsEmpty();
        while(nNumber!=0)
        {
            m_pOwner->m_strNumber+=(TCHAR)('0'+nNumber%10);
            nNumber/=10;
        }
        m_pOwner->m_strNumber.MakeReverse();
        if(fSyncChecked)
            sLock.Unlock();
        if(m_pOwner->IsDlgButtonChecked(IDC_SHOWCNTRTHRD))
            m_pOwner->AddToListBox(_T("Counter: Add 1"));
    }
    m_pOwner->PostMessage(WM_CLOSE,0,0L);
    return 0;
}
BEGIN_MESSAGE_MAP(CCounterThread, CExampleThread)
//{{AFX_MSG_MAP(CCounterThread)
    //NOTE-the Class Wizard will add and revove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
IMPLEMENT_DYNCREATE(CDisplayThread,CExampleThread)
int CDisplayThread::Run()
{
    BOOL fSyncChecked;
    CString strBuffer;
    ASSERT(m_pOwner!=NULL);
        if(m_pOwner==NULL)
            return -1;
    CSingleLock sLock(&(m_pOwner->m_mutex));
    while(!m_bDone)
    {
        fSyncChecked=m_pOwner->IsDlgButtonChecked(IDC_SYNCHRONIZE);
        if(fSyncChecked)
            sLock.Lock();
        strBuffer=_T("Display:");
        strBuffer+=m_pOwner->m_strNumber;
        if(fSyncChecked)
            sLock.Unlock();
        m_pOwner->AddToListBox(strBuffer);
    }
    m_pOwner->PostMessage(WM_CLOSE,0,0L);
    return 0;
}
BEGIN_MESSAGE_MAP(CDisplayThread,CExampleThread)
//{{AFX_MSG_MAP(CDisplayThread)
      //NOTE-the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

代码如下:
// MultiThreadDlg.h : header file
//
#if !defined(AFX_MULTITHREADDLG_H__162F3F84_AB2C_4167_A04F_5CABB7B16FAE__INCLUDED_)
#define AFX_MULTITHREADDLG_H__162F3F84_AB2C_4167_A04F_5CABB7B16FAE__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <afxmt.h>
//
/////////////////////////////////////////////////////////////////////////////
// CMultiThreadDlg dialog
class CMultiThreadDlg : public CDialog
{
// Construction
    friend class CDisplayThread;
    friend class CCounterThread;
public:
    CMultiThreadDlg(CWnd* pParent = NULL);    // standard constructor
public:
    CString m_strNumber;
    CMutex  m_mutex;
    CCounterThread* m_pCounterThread;
    CDisplayThread* m_pDisplayThread;
    void AddToListBox(LPCTSTR szBuffer);
    void PriorityChange(UINT nID);
// Dialog Data
    //{{AFX_DATA(CMultiThreadDlg)
    enum { IDD = IDD_MULTITHREAD_DIALOG };
    CString    m_strBuffer;
    //}}AFX_DATA
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CMultiThreadDlg)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //}}AFX_VIRTUAL
// Implementation
protected:
    HICON m_hIcon;
    // Generated message map functions
    //{{AFX_MSG(CMultiThreadDlg)
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnSelchangePriorityclass();
    afx_msg void OnSelchangeCntrthrdpriority();
    afx_msg void OnSelchangeDspythrdpriority();
    afx_msg void OnPause();
    afx_msg void OnClose();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MULTITHREADDLG_H__162F3F84_AB2C_4167_A04F_5CABB7B16FAE__INCLUDED_)
// MultiThreadDlg.cpp : implementation file
//
#include "stdafx.h"
#include "MultiThread.h"
#include "MultiThreadDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "ExampleThread.h"
/////////////////////////////////////////////////////////////////////////////
// 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()
/////////////////////////////////////////////////////////////////////////////
// CMultiThreadDlg dialog
CMultiThreadDlg::CMultiThreadDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CMultiThreadDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CMultiThreadDlg)
    m_strBuffer = _T("");
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMultiThreadDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CMultiThreadDlg)
    DDX_LBString(pDX, IDC_DATABOX, m_strBuffer);
    //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMultiThreadDlg, CDialog)
    //{{AFX_MSG_MAP(CMultiThreadDlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_CBN_SELCHANGE(IDC_PRIORITYCLASS, OnSelchangePriorityclass)
    ON_CBN_SELCHANGE(IDC_CNTRTHRDPRIORITY, OnSelchangeCntrthrdpriority)
    ON_CBN_SELCHANGE(IDC_DSPYTHRDPRIORITY, OnSelchangeDspythrdpriority)
    ON_BN_CLICKED(IDC_PAUSE, OnPause)
    ON_WM_CLOSE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMultiThreadDlg message handlers
BOOL CMultiThreadDlg::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
    CComboBox* pBox;
    pBox=(CComboBox*)GetDlgItem(IDC_PRIORITYCLASS);
    ASSERT(pBox!=NULL);
    if(pBox!=NULL)
    {
        pBox->AddString(_T("Idle"));
        pBox->AddString(_T("Normal"));
        pBox->AddString(_T("High"));
        pBox->AddString(_T("Realtime"));
        pBox->SetCurSel(1);
//        pBox->SelectString(-1,"Normal");
    }
    pBox=(CComboBox*)GetDlgItem(IDC_DSPYTHRDPRIORITY);
    ASSERT(pBox!=NULL);
        if(pBox!=NULL)
    {
        pBox->AddString(_T("Idle"));
        pBox->AddString(_T("Lowest"));
        pBox->AddString(_T("Below Normal"));
        pBox->AddString(_T("Below Normal"));
        pBox->AddString(_T("Normal"));
        pBox->AddString(_T("Above Normal"));
        pBox->AddString(_T("Highest"));
        pBox->AddString(_T("Timecritical"));
        pBox->SetCurSel(3);
//        pBox->SelectString(-1,"Normal");
    }
    pBox=(CComboBox*)GetDlgItem(IDC_CNTRTHRDPRIORITY);
    ASSERT(pBox!=NULL);
        if(pBox!=NULL)
    {
        pBox->AddString(_T("Idle"));
        pBox->AddString(_T("Lowest"));
        pBox->AddString(_T("Below Normal"));
        pBox->AddString(_T("Below Normal"));
        pBox->AddString(_T("Normal"));
        pBox->AddString(_T("Above Normal"));
        pBox->AddString(_T("Highest"));
        pBox->AddString(_T("Timecritical"));
        pBox->SetCurSel(3);
//        pBox->SelectString(-1,"Normal");
    }
CButton* pCheck=(CButton*)GetDlgItem(IDC_PAUSE);
pCheck->SetCheck(1);
m_pDisplayThread=(CDisplayThread*)AfxBeginThread(RUNTIME_CLASS(CDisplayThread),
                                                 THREAD_PRIORITY_NORMAL,
                                                 0,
                                                 CREATE_SUSPENDED);
m_pDisplayThread->SetOwner(this);
m_pCounterThread=(CCounterThread*)AfxBeginThread(RUNTIME_CLASS(CCounterThread),
                                                 THREAD_PRIORITY_NORMAL,
                                                 0,
                                                 CREATE_SUSPENDED);
m_pCounterThread->SetOwner(this);
    
    return TRUE;  // return TRUE  unless you set the focus to a control
}
void CMultiThreadDlg::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 CMultiThreadDlg::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 CMultiThreadDlg::OnQueryDragIcon()
{
    return (HCURSOR) m_hIcon;
}
void CMultiThreadDlg::AddToListBox(LPCTSTR szBuffer)
{
    CListBox* pBox=(CListBox*)GetDlgItem(IDC_DATABOX);
    ASSERT(pBox!=NULL);
    if(pBox!=NULL)
    {
        int x=pBox->AddString(szBuffer);
        pBox->SetCurSel(x);
        if(pBox->GetCount()>100)
            pBox->DeleteString(0);
    }
}
void CMultiThreadDlg::PriorityChange(UINT nID)
{
    ASSERT(nID==IDC_CNTRTHRDPRIORITY||nID==IDC_DSPYTHRDPRIORITY);    
    DWORD dw;
    CComboBox* pBox=(CComboBox*)GetDlgItem(nID);
    int nCurSel=pBox->GetCurSel();
    switch(nCurSel)
    {
    case 0:
        dw=(DWORD)THREAD_PRIORITY_IDLE;
        break;
    case 1:
        dw=(DWORD)THREAD_PRIORITY_LOWEST;
        break;
    case 2:
        dw=(DWORD)THREAD_PRIORITY_BELOW_NORMAL;
        break;
    case 3:
        dw=(DWORD)THREAD_PRIORITY_NORMAL;
        break;
    case 4:
        dw=(DWORD)THREAD_PRIORITY_ABOVE_NORMAL;
        break;
    case 5:
         dw=(DWORD)THREAD_PRIORITY_HIGHEST;
         break;
    case 6:
         dw=(DWORD)THREAD_PRIORITY_TIME_CRITICAL;
         break;
    default:
         dw=(DWORD)THREAD_PRIORITY_NORMAL;
         break;
    }
    if(nID==IDC_CNTRTHRDPRIORITY)
        m_pCounterThread->SetThreadPriority(dw);
    else
        m_pDisplayThread->SetThreadPriority(dw);
}
        
void CMultiThreadDlg::OnSelchangePriorityclass() 
{
    DWORD dw;
    CComboBox* pBox=(CComboBox*)GetDlgItem(IDC_PRIORITYCLASS);
    int nCurSel=pBox->GetCurSel();
    switch(nCurSel)
    {
    case 0:
        dw=IDLE_PRIORITY_CLASS;
        break;
    case 1:
        dw=NORMAL_PRIORITY_CLASS;
        break;
    case 2:
        dw=HIGH_PRIORITY_CLASS;
        break;
    case 3:
        dw=REALTIME_PRIORITY_CLASS;
        break;
    default:
        dw=NORMAL_PRIORITY_CLASS;
        break;
    }
    SetPriorityClass(GetCurrentProcess(), dw);
}
void CMultiThreadDlg::OnSelchangeCntrthrdpriority() 
{
    // TODO: Add your control notification handler code here
    DWORD dw;
    CComboBox* pBox=(CComboBox*)GetDlgItem(IDC_DSPYTHRDPRIORITY);
    int nCurSel=pBox->GetCurSel();
    switch(nCurSel)
    {
    case 0:
        dw=IDLE_PRIORITY_CLASS;
        break;
    case 1:
        dw=NORMAL_PRIORITY_CLASS;
        break;
    case 2:
        dw=HIGH_PRIORITY_CLASS;
        break;
    case 3:
        dw=REALTIME_PRIORITY_CLASS;
        break;
    default:
        dw=NORMAL_PRIORITY_CLASS;
        break;
    }
    SetPriorityClass(GetCurrentProcess(), dw);    
}
void CMultiThreadDlg::OnSelchangeDspythrdpriority() 
{
    // TODO: Add your control notification handler code here
    DWORD dw;
    CComboBox* pBox=(CComboBox*)GetDlgItem(IDC_CNTRTHRDPRIORITY);
    int nCurSel=pBox->GetCurSel();
    switch(nCurSel)
    {
    case 0:
        dw=IDLE_PRIORITY_CLASS;
        break;
    case 1:
        dw=NORMAL_PRIORITY_CLASS;
        break;
    case 2:
        dw=HIGH_PRIORITY_CLASS;
        break;
    case 3:
        dw=REALTIME_PRIORITY_CLASS;
        break;
    default:
        dw=NORMAL_PRIORITY_CLASS;
        break;
    }
    SetPriorityClass(GetCurrentProcess(), dw);    
}
void CMultiThreadDlg::OnPause() 
{
    // TODO: Add your control notification handler code here
    CButton* pCheck=(CButton*)GetDlgItem(IDC_PAUSE);
    BOOL bPaused=((pCheck->GetState()&0x003)!=3);
    if(bPaused)
    {
        m_pCounterThread->SuspendThread();
        m_pDisplayThread->SuspendThread();
    }
    else
    {
        m_pCounterThread->ResumeThread();
        m_pDisplayThread->ResumeThread();
    }
    
}
void CMultiThreadDlg::OnClose() 
{
    // TODO: Add your message handler code here and/or call default
    int nCount=0;
    DWORD dwStatus;
    CButton* pCheck=(CButton*)GetDlgItem(IDC_PAUSE);
    BOOL bPaused=((pCheck->GetState()&0x003)!=0);
    if(bPaused==TRUE)
    {
        pCheck->SetCheck(0);
        m_pCounterThread->ResumeThread();
        m_pDisplayThread->ResumeThread();
    }
    if(m_pCounterThread!=NULL)
    {
        VERIFY(::GetExitCodeThread(m_pCounterThread->m_hThread,&dwStatus));
        if(dwStatus==STILL_ACTIVE)
        {
            nCount++;
            m_pCounterThread->m_bDone=TRUE;
        }
        else
        {
            delete m_pCounterThread;
            m_pCounterThread=NULL;
        }
    }
    if(m_pDisplayThread!=NULL)
    {
        VERIFY(::GetExitCodeThread(m_pDisplayThread->m_hThread,&dwStatus));
        if(dwStatus==STILL_ACTIVE)
        {
            nCount++;
            m_pDisplayThread->m_bDone=TRUE;
        }
        else
        {
            delete m_pDisplayThread;
            m_pDisplayThread=NULL;
        }
    }
    if(nCount==0)
        CDialog::OnClose();
    else
        PostMessage(WM_CLOSE,0,0);
  CDialog::OnClose();
}
 
