MFC支持两种线程:用户界面线程和工作线程
区别如下:
1)用户界面线程:处理用户输入及相应用户生成事件和消息,并独立响应应用程序其他部分执行线程的消息和时间,它包含一个a Message Pump,使用消息循环来处理各种事件。
2)工作线程:运行于后台,处理不需要用户输入且耗时巨大的任务。
win32API中不区分两种线程,只需要知道线程的起始地址就可以开始执行线程。MFC中,用户界面线程和工作线程的基类都是CWinThread类。二者的区别是,对于用户界面线程,需要先从CWinTread类派生出自己的线程类,而对于工作线程,用户只需调用MFC框架的AfxBeginThread函数即可创建CWinTread对象。也就是说工作线程的创建相对简单一些。
- 创建工作线程的例子(比较简单):
步骤如下:(1)线程控制函数的编写
struct { //其实这个结构体也可以是空的,也可以只作为控制函数的入口参数
int n;
double* pD;
}myData;
myData ss;//定义了该类型的变量,对该变量的初始化的代码省略了
UNIT MyCalcFunc(LPVOID pParam)
{
return 0;
}
(2)在程序的主线程中调用AfxBeginTread()来创建并启动和运行线程。此函数会将控制函数名(函数地址)和结构变量的地址作为参数来传递。
AfxBeginThread(MyCalcFunc,&ss);//其他参数可以省略,表示默认
- 创建用户界面线程的例子:
步骤如下:(1)从CWinThread类派生出自己的线程类,借助ClassWizard来实现
(2)改造这个线程,实现需要的功能
(i)在这个线程类的.h头文件中,使用DECLARE_DYNCRATE宏来声明这个类;在用户线程类的.cpp实现文件中,使用IMPLEMENT_DYNCREATE宏来实现这个类。前者的调用格式是: DECLARE_DYNCRATE(class_name),其中class_name中是实际的类名。
(ii)如果在一个类中宣布使用了DECLARE_DYNCRATE宏,那么就必须在这个类的.cpp实现文件中,使用IMPLEMENT_DYNCREATE宏。它的调用格式是:
IMPLEMENT_DYNCREATE(class_name, base_class_name) 参数是实际的线程类名和它的基类名。
(iii)这个线程类必须重载它的基类(CWinThread类)的某些成员函数,如该类的InitInstance()成员函数;对于基类的其它成员函数,可以有选择的重载,也可以使用缺省函数。
//CUIThreadDlg.h
#pragma once
# include"Resource.h"
// CUIThreadDlg 对话框
class CUIThreadDlg : public CDialog
{
DECLARE_DYNAMIC(CUIThreadDlg)
public:
CUIThreadDlg(CWnd* pParent = NULL); // 标准构造函数
virtual ~CUIThreadDlg();
// 对话框数据
enum { IDD = IDD_UITHREADDLG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
protected:
public:
afx_msg void OnBnClickedOk();
};
//UIThread.cpp
#include "stdafx.h"
#include "UIThread.h"
IMPLEMENT_DYNCREATE(CUIThread, CWinThread)
CUIThread::CUIThread(void)
{
}
CUIThread::~CUIThread(void)
{
}
BOOL CUIThread::InitInstance()
{
m_dlg.Create(IDD_UITHREADDLG);
m_dlg.ShowWindow(SW_SHOW);
// m_pMainWnd=&m_dlg;
// m_dlg.DoModal();
return TRUE;
}
int CUIThread::ExitInstance()
{
m_dlg.DestroyWindow();
// m_dlg.DestroyWindow();
return CWinThread::ExitInstance();
}
BEGIN_MESSAGE_MAP(CUIThread, CWinThread)
END_MESSAGE_MAP()
(3)创建并启动用户界面线程:要创建并启动用户界面线程,可以使用MFC提供的AfxBeginThread()函数的另一个版本,其格式是:
CWinThread* AfxBeginThread(
CRuntimeClass* pThreadClass,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );
具体实现方式就是在MFC主线程里面某个地方调用它
void CMultiThread6Dlg::OnBnClickedUiThread()
{
// TODO: 在此添加控件通知处理程序代码
// CWinThread *pThread=AfxBeginThread(RUNTIME_CLASS(CUIThread));
AfxBeginThread(RUNTIME_CLASS(CUIThread));
// CWinThread *pthread=AfxBeginThread(RUNTIME_CLASS(CUIThread));
}