继续学习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
 
原创粉丝点击