实例嘛,就不多做太多说明了。这里不说worker线程的使用,那种挂回调的东西,不说了。而且几乎不可控的。这里只说派生CWinThread方式。这里基于对话框工程给出实例。
1、派生CWinThread,不要自己写代码了,直接,类视图--右键add class -- mfc class -- base class设置为CWinThread。
2、添加消息处理,得到的完整的类代码如下:
- #pragma once
- #define WM_TEST WM_USER + 105
- // MyThread
- class MyThread : public CWinThread
- {
- DECLARE_DYNCREATE(MyThread)
- protected:
- MyThread(); // protected constructor used by dynamic creation
- virtual ~MyThread();
- public:
- virtual BOOL InitInstance();
- virtual int ExitInstance();
- void OnTest(WPARAM wParam, LPARAM lParam);
- protected:
- DECLARE_MESSAGE_MAP()
- };
- // MyThread.cpp : implementation file
- //
- #include "stdafx.h"
- #include "ThreadDlg.h"
- #include "MyThread.h"
- // MyThread
- IMPLEMENT_DYNCREATE(MyThread, CWinThread)
- MyThread::MyThread()
- {
- }
- MyThread::~MyThread()
- {
- }
- BOOL MyThread::InitInstance()
- {
- // TODO: perform and per-thread initialization here
- return TRUE;
- }
- int MyThread::ExitInstance()
- {
- // TODO: perform any per-thread cleanup here
- return CWinThread::ExitInstance();
- }
- void MyThread::OnTest(WPARAM wParam,LPARAM lParam)
- {
- AfxMessageBox("test");
- }
- BEGIN_MESSAGE_MAP(MyThread, CWinThread)
- ON_THREAD_MESSAGE(WM_TEST, OnTest)
- END_MESSAGE_MAP()
- // MyThread message handlers
3、对话框类如下,添加了多线程成员指针:
- class CThreadDlgDlg : public CDialogEx
- {
- private:
- MyThread *myThr;
4、修改函数CThreadDlgDlg::OnInitDialog():
- BOOL CThreadDlgDlg::OnInitDialog()
- {
- CDialogEx::OnInitDialog();
- // 将“关于...”菜单项添加到系统菜单中。
- // IDM_ABOUTBOX 必须在系统命令范围内。
- ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
- ASSERT(IDM_ABOUTBOX < 0xF000);
- CMenu* pSysMenu = GetSystemMenu(FALSE);
- if (pSysMenu != NULL)
- {
- BOOL bNameValid;
- CString strAboutMenu;
- bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
- ASSERT(bNameValid);
- if (!strAboutMenu.IsEmpty())
- {
- pSysMenu->AppendMenu(MF_SEPARATOR);
- pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
- }
- }
- // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
- // 执行此操作
- SetIcon(m_hIcon, TRUE); // 设置大图标
- SetIcon(m_hIcon, FALSE); // 设置小图标
- // TODO: 在此添加额外的初始化代码
- myThr = (MyThread *)AfxBeginThread(RUNTIME_CLASS(MyThread));
- return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
- }
5、对话框添加一个按钮,实现点击事件函数:
- void CThreadDlgDlg::OnBnClickedButton1()
- {
- // TODO: Add your control notification handler code here
- myThr->PostThreadMessage(WM_TEST, 0, 0);
- }
每次点击按钮,就会出发多线程的test函数了。
6、要线程退出怎么办?对于worker线程,就是一个回调这种,没有多大问题,要么用AfxEndThread要么直接return在回调函数里面,那么线程就退出了。但是对于ui线程,就没有那么容易了,msdn说了,可以直接在线程里面调用PostQuitMessage,但是要注意是在线程的执行体里面,如果是像上面的(5)里面说的,用myThr call PostQuitMessage这个成员函数,那么退出的一定是整个程序。还有一个办法就是发QUIT消息:
- void CThreadDlgDlg::OnBnClickedButton1()
- {
- // TODO: Add your control notification handler code here
- myThr->PostThreadMessage(WM_QUIT, 0, 0);
- }
7、线程间通信,同步互斥,以worker线程为例子,在dlg类里面添加一个CSemaphore成员,然后在构造函数里面初始化为0,先看一下CSemaphore的构造函数:
- CSemaphore(
- LONG lInitialCount = 1,
- LONG lMaxCount = 1,
- LPCTSTR pstrName = NULL,
- LPSECURITY_ATTRIBUTES lpsaAttributes = NULL
- );
下面列出完整源代码:
- // CDlgOncloseDlg dialog
- class CDlgOncloseDlg : public CDialogEx
- {
- // Construction
- public:
- CDlgOncloseDlg(CWnd* pParent = NULL); // standard constructor
- // Dialog Data
- enum { IDD = IDD_DLGONCLOSE_DIALOG };
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- // Implementation
- protected:
- HICON m_hIcon;
- // Generated message map functions
- virtual BOOL OnInitDialog();
- afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
- afx_msg void OnPaint();
- afx_msg HCURSOR OnQueryDragIcon();
- DECLARE_MESSAGE_MAP()
- public:
- afx_msg void OnBnClickedButtonNewThr();
- private:
- CWinThread *WorkThr;
- CSemaphore mySem;
- public:
- afx_msg void OnBnClickedButtonNewThr2();
- };
- CDlgOncloseDlg::CDlgOncloseDlg(CWnd* pParent /*=NULL*/)
- : CDialogEx(CDlgOncloseDlg::IDD, pParent),
- mySem(0)
- {
- m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
- }
- void CDlgOncloseDlg::DoDataExchange(CDataExchange* pDX)
- {
- CDialogEx::DoDataExchange(pDX);
- }
- BEGIN_MESSAGE_MAP(CDlgOncloseDlg, CDialogEx)
- ON_WM_SYSCOMMAND()
- ON_WM_PAINT()
- ON_WM_QUERYDRAGICON()
- ON_BN_CLICKED(IDC_BUTTON_NEW_THR, &CDlgOncloseDlg::OnBnClickedButtonNewThr)
- ON_BN_CLICKED(IDC_BUTTON_NEW_THR2, &CDlgOncloseDlg::OnBnClickedButtonNewThr2)
- END_MESSAGE_MAP()
- UINT myThread(LPVOID pParam)
- {
- CSemaphore *mySem;
- if(!pParam)
- {
- return -1;
- }
- else
- {
- mySem = (CSemaphore *)pParam;
- }
- while(1)
- {
- mySem->Lock();
- TRACE("myThread\n");
- }
- return 0;
- }
- void CDlgOncloseDlg::OnBnClickedButtonNewThr()
- {
- // TODO: Add your control notification handler code here
- WorkThr = AfxBeginThread(myThread, (LPVOID)&mySem);
- }
- void CDlgOncloseDlg::OnBnClickedButtonNewThr2()
- {
- // TODO: Add your control notification handler code here
- TRACE("OnBnClickedButtonNewThr2\n");
- mySem.Unlock();
- }
当然,Worker线程最大的作用就是,让它做一些复杂的事情,把主线程释放出来,这里做一个worker,然后主线程等worker完成:
- UINT ReadFile(LPVOID in)
- {
- CSemaphore *inSem = (CSemaphore *)in;
- if(!in)
- {
- return 0;
- }
- for(int i = 1000000000; i > 0; i--)
- ;
- inSem->Unlock();
- return 0;
- }
- void CMFCApplication1View::OnFileOpen()
- {
- if(!dlg )
- {
- dlg = new CtestDlg;
- dlg->Create(this);
- dlg->ModifyStyleEx(0, WS_EX_TOPMOST);
- }
- dlg->ShowWindow(SW_SHOW);
- AfxBeginThread(ReadFile, &sem);
- sem.Lock();
- dlg->DestroyWindow();
- delete dlg;
- dlg = NULL;
- }
8、UI线程,创建对话框:
添加对话框,添加相应的类为ThrTestDlg,添加成员函数CreateDlg()用于非模态对话框创建时候使用,这里列出完整类定义:
- class ThrTestDlg : public CDialogEx
- {
- DECLARE_DYNAMIC(ThrTestDlg)
- public:
- BOOL CreateDlg()
- {
- return CDialogEx::Create(IDD);
- }
- public:
- ThrTestDlg(CWnd* pParent = NULL); // standard constructor
- virtual ~ThrTestDlg();
- // Dialog Data
- enum { IDD = IDD_DIALOG1 };
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- DECLARE_MESSAGE_MAP()
- };
然后,修改UI线程类定义,在init和exit函数里面,实现创建和销毁对话框:
- class CMyThread : public CWinThread
- {
- DECLARE_DYNCREATE(CMyThread)
- protected:
- CMyThread(); // protected constructor used by dynamic creation
- virtual ~CMyThread();
- public:
- virtual BOOL InitInstance();
- virtual int ExitInstance();
- void end()
- {
- this->PostThreadMessage(WM_QUIT, 0, 0);
- }
- ThrTestDlg *dlg;
- protected:
- DECLARE_MESSAGE_MAP()
- };
- // CMyThread
- IMPLEMENT_DYNCREATE(CMyThread, CWinThread)
- CMyThread::CMyThread()
- {
- dlg = new ThrTestDlg();
- }
- CMyThread::~CMyThread()
- {
- delete dlg;
- }
- BOOL CMyThread::InitInstance()
- {
- // TODO: perform and per-thread initialization here
- dlg->CreateDlg();
- dlg->ModifyStyleEx(0, WS_EX_TOPMOST);
- dlg->ShowWindow(SW_SHOW);
- return TRUE;
- }
- int CMyThread::ExitInstance()
- {
- // TODO: perform any per-thread cleanup here
- dlg->DestroyWindow();
- return CWinThread::ExitInstance();
- }
- BEGIN_MESSAGE_MAP(CMyThread, CWinThread)
- END_MESSAGE_MAP()
再修改工程的对话框,添加两个按钮事件,一个做创建新线程,一个退出前者创建的线程。代码如下:
- void CDlgOncloseDlg::OnBnClickedButtonNewThr()
- {
- // TODO: Add your control notification handler code here
- WorkThr = AfxBeginThread(RUNTIME_CLASS(CMyThread));
- }
- void CDlgOncloseDlg::OnBnClickedButtonNewThr2()
- {
- // TODO: Add your control notification handler code here
- TRACE("OnBnClickedButtonNewThr2\n");
- WorkThr->PostThreadMessageW(WM_QUIT, 0, 0);
- //mySem.Unlock();
- }
Original URL:http://blog.csdn.net/ztz0223/article/details/9026957