继续学习MFC——第11章多线程技术
来源:互联网 发布:阿里通网络电话软件 编辑:程序博客网 时间:2024/06/12 00:29
要知道MFC类一般不是线程安全的,这点要时刻牢记。
书中前两个小节简单说了一下进程和线程:
对于Windows平台,进程简而言之就是一个应用程序,线程实际上是处理器寄存器的一个映像。线程包括应用程序在哪儿执行代码和线程的本地变量等信息。进程可以有多个线程,共享该进程中的全局变量和资源,但是拥有各自的执行点和本地变量。
MFC里面用CWinThread对象表示所有线程。CWinApp恰好从CWinThread派生,代表主线程。
为了使用一个线程,需要从CWinThread派生出自己的类,然后重载InitInstance, ExitInstance,并通过AfxBeginThread来创建线程对象。
CWinThread中包含几个成员变量和函数,我们关心如下几个:
成员
定义
m_pMainWnd
该线程的主窗口
m_pActiveWnd
当前活动窗口
m_hThread, m_nThreadID
线程句柄和ID
InitInstance, ExitInstance
重载提供线程的初始化和终结
PreTranslateMessage
过滤消息,处理快捷键
还有不少,到时候参考帮助文档吧。
线程同步,看MFC不如看Windows SDK更清楚一些,MFC提供的如下几个同步对象类:CEvent, CMutex, CSemaphore, CCriticalSection等。
书中给出了一个MFC多线程的例子,我感兴趣的地方是每个DLL函数入口都要求使用AFX_MANAGE_STATE宏,MFC源代码中也有不少地方在使用。让我们仔细研究一下它。
典型用法为:AFX_MANAGE_STATE(AfxGetStaticModuleState());
该宏定义在afxstat_.h中(VC7):
#define AFX_MANAGE_STATE(p) AFX_MAINTAIN_STATE2 _ctlState(p); // 用 p 构造结构
注意:仅当 _AFXDLL被定义时才有。无 _AFXDLL定义时该宏什么也不做。
其中AFX_MAINTAIN_STATE2定义为一个结构:
struct AFX_MAINTAIN_STATE2
{
explicit AFX_MAINTAIN_STATE2(AFX_MODULE_STATE* pModuleState); // 显式构造函数。
~AFX_MAINTAIN_STATE2(); // 这里面一定还干着什么勾当,我们一会去看
protected:
AFX_MODULE_STATE* m_pPrevModuleState; // 下面接着去看
_AFX_THREAD_STATE* m_pThreadState;
};
先看看AfxGetStaticModuleState()函数:(实现于dllmodul.cpp)
static _AFX_DLL_MODULE_STATE afxModuleState; // 在_AFXDLL定义下生效
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()
{
AFX_MODULE_STATE* pModuleState = &afxModuleState; // 返回模块状态对象地址
return pModuleState;
}
_AFX_DLL_MODULE_STATE的定义如下:
class _AFX_DLL_MODULE_STATE : public AFX_MODULE_STATE // 派生于 AFX_MODULE_STATE
{
public:
// AfxWndProcDllStatic 函数包装 AfxWndProc 调用,在前面调用 AFX_MANAGE_STATE
_AFX_DLL_MODULE_STATE() : AFX_MODULE_STATE(TRUE, AfxWndProcDllStatic, _MFC_VER) {}
};
LRESULT CALLBACK AfxWndProcDllStatic(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
AFX_MANAGE_STATE(&afxModuleState); // 哦,这里也。。。
return AfxWndProc(hWnd, nMsg, wParam, lParam);
}
下面是AFX_MODULE_STATE的定义,好复杂呀:
// AFX_MODULE_STATE (global data for a module)
class AFX_MODULE_STATE : public CNoTrackObject
{
public:
// 仔细观察这个构造函数的参数名字和类型
AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD dwVersion,BOOL bSystem = FALSE);
~AFX_MODULE_STATE();
CWinApp* m_pCurrentWinApp; // AfxGetApp() 返回就是它
HINSTANCE m_hCurrentInstanceHandle; // AfxGetInstanceHandle() 返回它
HINSTANCE m_hCurrentResourceHandle; // AfxGetResourceHandle() 返回它
LPCTSTR m_lpszCurrentAppName; // AfxGetAppName() 返回它
BYTE m_bDLL; // TRUE if module is a DLL, FALSE if it is an EXE
BYTE m_bSystem; // TRUE if module is a "system" module, FALSE if not
BYTE m_bReserved[2]; // padding
WNDPROC m_pfnAfxWndProc;
DWORD m_dwVersion; // version that module linked against
// define thread local portions of module state
CThreadLocal<AFX_MODULE_THREAD_STATE> m_thread; // 这是一个线程局部变量
// 这下面还有一大堆我们删减掉了。。。
};
注意:有些成员外面带有_AFXDLL宏定义才生效的我们删减掉了。
这时,我们应该知道前面的afxModuleState里面都有些什么东西啦。
现在我们明白了AfxGetStaticModuleState()返回了什么,让我们接着看AFX_MAINTAIN_STATE2的构造和析构函数:
AFX_MAINTAIN_STATE2::AFX_MAINTAIN_STATE2(AFX_MODULE_STATE* pNewState)
{
m_pThreadState = _afxThreadState; // ?好像是当前线程的状态
m_pPrevModuleState = m_pThreadState->m_pModuleState; // 保存原来的模块状态
m_pThreadState->m_pModuleState = pNewState; // 切换到新的模块
}
很奇怪,没有找到AFX_MAINTAIN_STATE2的析构函数,只能拿AFX_MAINTAIN_STATE的析构函数来分析了:(估计差不多)
AFX_MAINTAIN_STATE::~AFX_MAINTAIN_STATE()
{
_AFX_THREAD_STATE* pState = _afxThreadState;
pState->m_pModuleState = m_pPrevModuleState; // 恢复到原来保存的模块状态
}
至此,我们应该能够理解定义AFX_MAINTAIN_STATE2 _ctlState的含义了,在定义处调用了构造函数,完成模块状态切换;在析构(一般是函数返回处)中切换回去。
[好像噢]每个线程(CWinThread派生的)都有自己的线程状态(_afxThreadState),而HWND->CWnd, HMENU->CMenu, HDC->CDC, HGDIOBJ->CGdiObject等对象映射表都是线程相关的,所以。。。在一个线程无法映射另一个线程的HWND, HMENU等对象的:)
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=108827
- 继续学习MFC——第11章多线程技术
- 继续学习MFC——第11章多线程技术
- 继续学习MFC——第9章MFC和Interne
- 继续学习MFC——有关外壳图标处理过程
- 继续学习MFC——有关外壳图标处理过程
- 多线程编程学习2——MFC与多线程简介
- MFC--控制多线程,开启、暂停、继续、终止
- Java技术——Java多线程学习
- 深入浅出mfc 系列 第14章MFC 多线程程序设计
- 转载:《Win32多线程程序设计》学习笔记 第10章 MFC 中的线程
- 多线程编程学习3——使用MFC工作者线程
- 继续 《学习opencv》第三章习题第5,6题
- C++多线程同步技术(MFC)
- C++多线程同步技术(MFC)
- MFC多线程同步技术分析
- MFC多线程及同步技术
- MFC到底还要不要继续学习
- MFC多线程学习
- 用于快速计算的DUAL表
- 下载JDK API(CHM)所想到的
- 使用 ADO.NET 访问 Oracle 9i 存储过程使用 ADO.NET 访问 Oracle 9i 存储过程
- ASP.NET 2.0中实现跨页面提交
- 为什么要使用XML
- 继续学习MFC——第11章多线程技术
- Eclipse中的Content Assist
- DirectX的发展历程!
- ajax引擎以及后端服务器
- Subversion(SVN)安装使用指南
- vsftpd 配置手册
- WinXP之后如何安装Win2000
- 帮我分析一下这是不是心理疾病
- Torque游戏作品IGC欣赏(Torque Game Show:IGC)