MFC多线程CWinThread实例

实例嘛,就不多做太多说明了。这里不说worker线程的使用,那种挂回调的东西,不说了。而且几乎不可控的。这里只说派生CWinThread方式。这里基于对话框工程给出实例。

1、派生CWinThread,不要自己写代码了,直接,类视图--右键add class -- mfc class -- base class设置为CWinThread。

2、添加消息处理,得到的完整的类代码如下:

  1. #pragma once  
  2. #define WM_TEST  WM_USER + 105  
  3.   
  4. // MyThread  
  5.   
  6. class MyThread : public CWinThread  
  7. {  
  8.     DECLARE_DYNCREATE(MyThread)  
  9.   
  10. protected:  
  11.     MyThread();           // protected constructor used by dynamic creation  
  12.     virtual ~MyThread();  
  13.   
  14. public:  
  15.     virtual BOOL InitInstance();  
  16.     virtual int ExitInstance();  
  17.     void    OnTest(WPARAM wParam, LPARAM lParam);  
  18. protected:  
  19.     DECLARE_MESSAGE_MAP()  
  20. };  
  21.   
  22.   
  23. // MyThread.cpp : implementation file  
  24. //  
  25.   
  26. #include "stdafx.h"  
  27. #include "ThreadDlg.h"  
  28. #include "MyThread.h"  
  29.   
  30.   
  31. // MyThread  
  32.   
  33. IMPLEMENT_DYNCREATE(MyThread, CWinThread)  
  34.   
  35. MyThread::MyThread()  
  36. {  
  37. }  
  38.   
  39. MyThread::~MyThread()  
  40. {  
  41. }  
  42.   
  43. BOOL MyThread::InitInstance()  
  44. {  
  45.     // TODO:  perform and per-thread initialization here  
  46.     return TRUE;  
  47. }  
  48.   
  49. int MyThread::ExitInstance()  
  50. {  
  51.     // TODO:  perform any per-thread cleanup here  
  52.     return CWinThread::ExitInstance();  
  53. }  
  54.   
  55. void MyThread::OnTest(WPARAM wParam,LPARAM lParam)  
  56. {      
  57.     AfxMessageBox("test");  
  58. }  
  59.   
  60. BEGIN_MESSAGE_MAP(MyThread, CWinThread)  
  61.     ON_THREAD_MESSAGE(WM_TEST, OnTest)  
  62. END_MESSAGE_MAP()  
  63.   
  64.   
  65. // MyThread message handlers  

 

3、对话框类如下,添加了多线程成员指针:

  1. class CThreadDlgDlg : public CDialogEx  
  2. {  
  3. private:  
  4.     MyThread *myThr;  


4、修改函数CThreadDlgDlg::OnInitDialog():

  1. BOOL CThreadDlgDlg::OnInitDialog()  
  2. {  
  3.     CDialogEx::OnInitDialog();  
  4.   
  5.     // 将“关于...”菜单项添加到系统菜单中。  
  6.   
  7.     // IDM_ABOUTBOX 必须在系统命令范围内。  
  8.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  9.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  10.   
  11.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  12.     if (pSysMenu != NULL)  
  13.     {  
  14.         BOOL bNameValid;  
  15.         CString strAboutMenu;  
  16.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  17.         ASSERT(bNameValid);  
  18.         if (!strAboutMenu.IsEmpty())  
  19.         {  
  20.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  21.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  22.         }  
  23.     }  
  24.   
  25.     // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动  
  26.     //  执行此操作  
  27.     SetIcon(m_hIcon, TRUE);         // 设置大图标  
  28.     SetIcon(m_hIcon, FALSE);        // 设置小图标  
  29.   
  30.     // TODO: 在此添加额外的初始化代码  
  31.     myThr = (MyThread *)AfxBeginThread(RUNTIME_CLASS(MyThread));  
  32.   
  33.     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE  
  34. }  


5、对话框添加一个按钮,实现点击事件函数:

  1. void CThreadDlgDlg::OnBnClickedButton1()  
  2. {  
  3.     // TODO: Add your control notification handler code here  
  4.     myThr->PostThreadMessage(WM_TEST, 0, 0);  
  5. }  

每次点击按钮,就会出发多线程的test函数了。

6、要线程退出怎么办?对于worker线程,就是一个回调这种,没有多大问题,要么用AfxEndThread要么直接return在回调函数里面,那么线程就退出了。但是对于ui线程,就没有那么容易了,msdn说了,可以直接在线程里面调用PostQuitMessage,但是要注意是在线程的执行体里面,如果是像上面的(5)里面说的,用myThr call PostQuitMessage这个成员函数,那么退出的一定是整个程序。还有一个办法就是发QUIT消息:

  1. void CThreadDlgDlg::OnBnClickedButton1()  
  2. {  
  3.     // TODO: Add your control notification handler code here  
  4.     myThr->PostThreadMessage(WM_QUIT, 0, 0);  
  5. }  

7、线程间通信,同步互斥,以worker线程为例子,在dlg类里面添加一个CSemaphore成员,然后在构造函数里面初始化为0,先看一下CSemaphore的构造函数:

  1. CSemaphore(  
  2.    LONG lInitialCount = 1,  
  3.    LONG lMaxCount = 1,  
  4.    LPCTSTR pstrName = NULL,  
  5.    LPSECURITY_ATTRIBUTES lpsaAttributes = NULL   
  6. );  

下面列出完整源代码:

  1. // CDlgOncloseDlg dialog  
  2. class CDlgOncloseDlg : public CDialogEx  
  3. {  
  4.     // Construction  
  5. public:  
  6.     CDlgOncloseDlg(CWnd* pParent = NULL);   // standard constructor  
  7.   
  8.     // Dialog Data  
  9.     enum { IDD = IDD_DLGONCLOSE_DIALOG };  
  10.   
  11. protected:  
  12.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support  
  13.   
  14.   
  15.     // Implementation  
  16. protected:  
  17.     HICON m_hIcon;  
  18.   
  19.     // Generated message map functions  
  20.     virtual BOOL OnInitDialog();  
  21.     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);  
  22.     afx_msg void OnPaint();  
  23.     afx_msg HCURSOR OnQueryDragIcon();  
  24.     DECLARE_MESSAGE_MAP()  
  25. public:  
  26.     afx_msg void OnBnClickedButtonNewThr();  
  27.   
  28. private:  
  29.     CWinThread *WorkThr;  
  30.     CSemaphore mySem;  
  31. public:  
  32.     afx_msg void OnBnClickedButtonNewThr2();  
  33. };  
  34.   
  35. CDlgOncloseDlg::CDlgOncloseDlg(CWnd* pParent /*=NULL*/)  
  36.     : CDialogEx(CDlgOncloseDlg::IDD, pParent),  
  37.     mySem(0)  
  38. {  
  39.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  
  40. }  
  41.   
  42. void CDlgOncloseDlg::DoDataExchange(CDataExchange* pDX)  
  43. {  
  44.     CDialogEx::DoDataExchange(pDX);  
  45. }  
  46.   
  47. BEGIN_MESSAGE_MAP(CDlgOncloseDlg, CDialogEx)  
  48.     ON_WM_SYSCOMMAND()  
  49.     ON_WM_PAINT()  
  50.     ON_WM_QUERYDRAGICON()  
  51.     ON_BN_CLICKED(IDC_BUTTON_NEW_THR, &CDlgOncloseDlg::OnBnClickedButtonNewThr)  
  52.     ON_BN_CLICKED(IDC_BUTTON_NEW_THR2, &CDlgOncloseDlg::OnBnClickedButtonNewThr2)  
  53. END_MESSAGE_MAP()  
  54.   
  55.   
  56. UINT myThread(LPVOID pParam)  
  57. {  
  58.     CSemaphore *mySem;  
  59.   
  60.     if(!pParam)  
  61.     {  
  62.         return -1;  
  63.     }  
  64.     else  
  65.     {  
  66.         mySem = (CSemaphore *)pParam;  
  67.     }  
  68.   
  69.     while(1)  
  70.     {  
  71.         mySem->Lock();  
  72.         TRACE("myThread\n");  
  73.     }  
  74.   
  75.     return 0;  
  76. }  
  77.   
  78. void CDlgOncloseDlg::OnBnClickedButtonNewThr()  
  79. {  
  80.     // TODO: Add your control notification handler code here  
  81.   
  82.     WorkThr = AfxBeginThread(myThread, (LPVOID)&mySem);  
  83. }  
  84.   
  85.   
  86. void CDlgOncloseDlg::OnBnClickedButtonNewThr2()  
  87. {  
  88.     // TODO: Add your control notification handler code here  
  89.     TRACE("OnBnClickedButtonNewThr2\n");  
  90.     mySem.Unlock();  
  91. }  

当然,Worker线程最大的作用就是,让它做一些复杂的事情,把主线程释放出来,这里做一个worker,然后主线程等worker完成:

  1. UINT ReadFile(LPVOID in)  
  2. {  
  3.     CSemaphore *inSem = (CSemaphore *)in;  
  4.     if(!in)  
  5.     {  
  6.         return 0;  
  7.     }  
  8.     for(int i = 1000000000; i > 0; i--)  
  9.         ;  
  10.     inSem->Unlock();  
  11.   
  12.     return 0;  
  13. }  
  14.   
  15. void CMFCApplication1View::OnFileOpen()  
  16. {  
  17.     if(!dlg )  
  18.     {  
  19.         dlg = new CtestDlg;  
  20.         dlg->Create(this);  
  21.         dlg->ModifyStyleEx(0, WS_EX_TOPMOST);  
  22.     }  
  23.   
  24.     dlg->ShowWindow(SW_SHOW);  
  25.   
  26.     AfxBeginThread(ReadFile, &sem);  
  27.   
  28.     sem.Lock();  
  29.     dlg->DestroyWindow();  
  30.     delete dlg;  
  31.     dlg = NULL;  
  32. }  


 


8、UI线程,创建对话框:

添加对话框,添加相应的类为ThrTestDlg,添加成员函数CreateDlg()用于非模态对话框创建时候使用,这里列出完整类定义:

  1. class ThrTestDlg : public CDialogEx  
  2. {  
  3.     DECLARE_DYNAMIC(ThrTestDlg)  
  4.   
  5. public:  
  6.     BOOL CreateDlg()  
  7.     {  
  8.         return CDialogEx::Create(IDD);  
  9.     }  
  10. public:  
  11.     ThrTestDlg(CWnd* pParent = NULL);   // standard constructor  
  12.     virtual ~ThrTestDlg();  
  13.   
  14.     // Dialog Data  
  15.     enum { IDD = IDD_DIALOG1 };  
  16.   
  17. protected:  
  18.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support  
  19.   
  20.     DECLARE_MESSAGE_MAP()  
  21. };  

然后,修改UI线程类定义,在init和exit函数里面,实现创建和销毁对话框:

  1. class CMyThread : public CWinThread  
  2. {  
  3.     DECLARE_DYNCREATE(CMyThread)  
  4.   
  5. protected:  
  6.     CMyThread();           // protected constructor used by dynamic creation  
  7.     virtual ~CMyThread();  
  8.   
  9. public:  
  10.     virtual BOOL InitInstance();  
  11.     virtual int ExitInstance();  
  12.   
  13.     void end()  
  14.     {  
  15.         this->PostThreadMessage(WM_QUIT, 0, 0);  
  16.     }  
  17.   
  18.     ThrTestDlg *dlg;  
  19.   
  20. protected:  
  21.     DECLARE_MESSAGE_MAP()  
  22. };  
  23.   
  24.   
  25. // CMyThread  
  26.   
  27. IMPLEMENT_DYNCREATE(CMyThread, CWinThread)  
  28.   
  29. CMyThread::CMyThread()  
  30. {  
  31.     dlg = new ThrTestDlg();  
  32. }  
  33.   
  34. CMyThread::~CMyThread()  
  35. {  
  36.     delete dlg;  
  37. }  
  38.   
  39. BOOL CMyThread::InitInstance()  
  40. {  
  41.     // TODO:  perform and per-thread initialization here  
  42.     dlg->CreateDlg();  
  43.     dlg->ModifyStyleEx(0, WS_EX_TOPMOST);  
  44.     dlg->ShowWindow(SW_SHOW);  
  45.   
  46.     return TRUE;  
  47. }  
  48.   
  49. int CMyThread::ExitInstance()  
  50. {  
  51.     // TODO:  perform any per-thread cleanup here  
  52.     dlg->DestroyWindow();  
  53.     return CWinThread::ExitInstance();  
  54. }  
  55.   
  56. BEGIN_MESSAGE_MAP(CMyThread, CWinThread)  
  57. END_MESSAGE_MAP()  

再修改工程的对话框,添加两个按钮事件,一个做创建新线程,一个退出前者创建的线程。代码如下:

  1. void CDlgOncloseDlg::OnBnClickedButtonNewThr()  
  2. {  
  3.     // TODO: Add your control notification handler code here  
  4.   
  5.     WorkThr = AfxBeginThread(RUNTIME_CLASS(CMyThread));  
  6. }  
  7.   
  8.   
  9. void CDlgOncloseDlg::OnBnClickedButtonNewThr2()  
  10. {  
  11.     // TODO: Add your control notification handler code here  
  12.     TRACE("OnBnClickedButtonNewThr2\n");  
  13.     WorkThr->PostThreadMessageW(WM_QUIT, 0, 0);  
  14.     //mySem.Unlock();  
  15. }  


Original URL:http://blog.csdn.net/ztz0223/article/details/9026957

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值