mfcmfc虚拟货币交易平台台中总投资额从那个模块看呢

程序模块化设计 如何实现的 - VC/MFC当前位置:& &&&程序模块化设计 如何实现的程序模块化设计 如何实现的&&网友分享于:&&浏览:30次程序模块化设计 怎么实现的?最近正在琢磨&将以前开发的程序进行模块划分,开发的功能越多,
引入的第三方类、等文件也越来越多,造成程序维护起来臃肿、费力。
比如有负责通讯的数据采集的、数据存储的、实时报警的、数据推送的等。
请教有没有好的方法。我想的方式有2种:
&1)动态库方式---》程序动态加载。调用接口
&2)COM方式&&&----》不太熟悉,不用MFC开发&,能否用现有代码进行封装&??
大家都用哪种方式比较好一些??------解决方案--------------------COM基本上都是DLL方式,两种其实基本是一种。------解决方案--------------------dll吧,简单,好理解,调试容易,分析问题简单------解决方案--------------------封装成dll,定义好接口------解决方案--------------------还有静态库一招------解决方案--------------------一个功能 一个模块,就这样分.比较好理解.------解决方案--------------------动态库就行了,主要是看你自己怎么划分。
COM的话比较高级一点,看你项目的需求是否需要
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有MFC的模块状态【转】
4.&Module State
Module State保存着和Module相关的状态信息。Module是Windows的术语,代表任何一个可执行的代码文件,
EXE和DLL都是Module的一种。Module State有下面几种:
AFX_MODULE_STATE,保存MODULE的信息,是_AFX_BASE_MODULE_STATE和_AFX_DLL_MODULE_STATE的基类
_AFX_BASE_MODULE_STATE,保存MFC Module的状态信息,没有定义其他的成员
_AFX_DLL_MODULE_STATE,保存DLL的状态信息,没有定义其他的成员
AFX_MODULE_THREAD_STATE,保存主线程的有关状态信息,虽然AFX_MODULE_THREAD_STATE是保存的线程的状态信息,但是它只保存Module的主线程的状态信息,所以可以看作是Module
State的一种。
这些Module State保存了MFC中的大量重要信息:
CWinApp指针
资源Module的句柄
OLE相关信息
Activation Context
4.1&AFX_MODULE_STATE
AFX_MODULE_STATE的定义如下:
// AFX_MODULE_STATE (global data for a module)
class AFX_MODULE_STATE : public CNoTrackObject
#ifdef _AFXDLL
AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD
dwVersion,
&&&&&&&&&&&&&
BOOL bSystem = FALSE);
explicit AFX_MODULE_STATE(BOOL bDLL);
~AFX_MODULE_STATE();
CWinApp* m_pCurrentWinA
HINSTANCE m_hCurrentInstanceH
HINSTANCE m_hCurrentResourceH
LPCTSTR m_lpszCurrentAppN
// …… 其他成员,从略
可以看到:
AFX_MODULE_STATE从CNoTrackObject继承。CNoTrackObject定义了自己的new/delete保证自己不会被各种调试版本的new/delete来Track,以免自己被错误的当作Leak。
AFX_MODULE_STATE在DLL和非DLL(也就是EXE)的情况下具有不同的构造函数(和成员)
AFX_MODULE_STATE在成员中保存了一些和Module相关的重要信息
实际上,AFX_MODULE_STATE并没有被直接使用,而是作为_AFX_BASE_MODULE_STATE和_AFX_DLL_MODULE_STATE的基类:
_AFX_BASE_MODULE_STATE被用于Module,其定义如下:
class _AFX_BASE_MODULE_STATE : public AFX_MODULE_STATE
#ifdef _AFXDLL
_AFX_BASE_MODULE_STATE() : AFX_MODULE_STATE(TRUE, AfxWndProcBase,
_AFX_BASE_MODULE_STATE() : AFX_MODULE_STATE(TRUE)
&&&&&&&&&&&&&
PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState)
_AFX_DLL_MODULE_STATE和_AFX_BASE_MODULE_STATE类似,只是仅用于DLL:
class _AFX_DLL_MODULE_STATE : public AFX_MODULE_STATE
_AFX_DLL_MODULE_STATE() : AFX_MODULE_STATE(TRUE,
AfxWndProcDllStatic, _MFC_VER)
&&&&&&&&&&&&&
static _AFX_DLL_MODULE_STATE afxModuleS
这两个class都没有定义额外的成员,比较简单,只是传入到基类AFX_MODULE_STATE的参数不同。此外,他们定义的方式不太一样,前者使用的是PROCESS_LOCAL宏,定义了一个变量_afxBaseModuleState。后者只是简单的定义了一个static变量afxModuleState。
下面这些函数可以用来获得Module的State:
AfxGetModuleState
AfxGetModuleState首先获得_afxThreadState的m_pModuleState,如果当前的Thread
State的m_pModuleState返回NULL,说明当前的Thread
State没有正确的初始化(通常的原因是创建线程的时候调用的是CreateThread函数而非AfxBeginThread),则使用_afxBaseModuleState。
AFX_MODULE_STATE* AFXAPI AfxGetModuleState()
_AFX_THREAD_STATE* pState = _afxThreadS
ENSURE(pState);
AFX_MODULE_STATE* pR
if (pState-&m_pModuleState != NULL)
&&&&&&&&&&&&&
// thread state's module state serves as override
&&&&&&&&&&&&&
pResult = pState-&m_pModuleS
&&&&&&&&&&&&&
// otherwise, use global app state
&&&&&&&&&&&&&
pResult = _afxBaseModuleState.GetData();
ENSURE(pResult != NULL);
_afxBaseModuleState是用PROCESS_LOCAL定义的:
PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState)
它代表整个MFC Module的State。当你的程序是动态链接到MFC
DLL的时候,该State只有一份。如果你的程序是静态链接到MFC的话,有几个模块(EXE/DLL)静态链接到MFC,MFC的代码就有几份,那么_afxBaseModuleState也就有几份。
AfxGetStaticModuleState
AfxGetStaticModuleState在不同的Project下面有着不同的行为:在DLL项目中,AfxGetSaticModuleState返回afxModuleState,也就是定义好的_AFX_DLL_MODULE_STATE,而在非DLL项目中,AfxGetStaticModuleState直接调用AfxGetModuleState。可以看到,在DLL的情况下,必须使用AfxGetStaticModuleState才可以获得DLL本身的Module
#ifdef _AFXDLL
static _AFX_DLL_MODULE_STATE afxModuleS
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()
AFX_MODULE_STATE* pModuleState =
&afxModuleS
return pModuleS
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
return pModuleS
AfxGetAppModuleState
AfxGetAppModuleState是最简单的,直接返回_afxBaseModuleState:
AFX_MODULE_STATE* AFXAPI AfxGetAppModuleState()
return _afxBaseModuleState.GetData();
从上面的讨论可以看出,当前处于那个MFC Module的状态之中,返回的就是那个MFC
Module所相关联的CWinApp对象。如果你有多个Module都是动态链接到MFC
DLL的话,那么AfxGetAppModuleState返回的总是同一个CWinApp。
ily: 宋体; mso-fareast-theme-font:
minor-fareast"&_afxBaseModuleState也就有几份。
AfxGetStaticModuleState
AfxGetStaticModuleState在不同的Project下面有着不同的行为:在DLL项目中,AfxGetSaticModuleState返回afxModuleState,也就是定义好的_AFX_DLL_MODULE_STATE,而在非DLL项目中,AfxGetStaticModuleState直接调用AfxGetModuleState。可以看到,在DLL的情况下,必须使用AfxGetStaticModuleState才可以获得DLL本身的Module
#ifdef _AFXDLL
static _AFX_DLL_MODULE_STATE afxModuleS
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()
AFX_MODULE_STATE* pModuleState =
&afxModuleS
return pModuleS
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
return pModuleS
AfxGetAppModuleState
AfxGetAppModuleState是最简单的,直接返回_afxBaseModuleState:
AFX_MODULE_STATE* AFXAPI AfxGetAppModuleState()
return _afxBaseModuleState.GetData();
从上面的讨论可以看出,当前处于那个MFC Module的状态之中,返回的就是那个MFC
Module所相关联的CWinApp对象。如果你有多个Module都是动态链接到MFC
DLL的话,那么AfxGetAppModuleState返回的总是同一个CWinApp。
ily: 宋体; mso-fareast-theme-font:
minor-fareast"&_afxBaseModuleState也就有几份。
AfxGetStaticModuleState
AfxGetStaticModuleState在不同的Project下面有着不同的行为:在DLL项目中,AfxGetSaticModuleState返回afxModuleState,也就是定义好的_AFX_DLL_MODULE_STATE,而在非DLL项目中,AfxGetStaticModuleState直接调用AfxGetModuleState。可以看到,在DLL的情况下,必须使用AfxGetStaticModuleState才可以获得DLL本身的Module
#ifdef _AFXDLL
static _AFX_DLL_MODULE_STATE afxModuleS
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()
AFX_MODULE_STATE* pModuleState =
&afxModuleS
return pModuleS
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
return pModuleS
AfxGetAppModuleState
AfxGetAppModuleState是最简单的,直接返回_afxBaseModuleState:
AFX_MODULE_STATE* AFXAPI AfxGetAppModuleState()
return _afxBaseModuleState.GetData();
从上面的讨论可以看出,当前处于那个MFC Module的状态之中,返回的就是那个MFC
Module所相关联的CWinApp对象。如果你有多个Module都是动态链接到MFC
DLL的话,那么AfxGetAppModuleState返回的总是同一个CWinApp。
ily: 宋体; mso-fareast-theme-font:
minor-fareast"&_afxBaseModuleState也就有几份。
AfxGetStaticModuleState
AfxGetStaticModuleState在不同的Project下面有着不同的行为:在DLL项目中,AfxGetSaticModuleState返回afxModuleState,也就是定义好的_AFX_DLL_MODULE_STATE,而在非DLL项目中,AfxGetStaticModuleState直接调用AfxGetModuleState。可以看到,在DLL的情况下,必须使用AfxGetStaticModuleState才可以获得DLL本身的Module
#ifdef _AFXDLL
static _AFX_DLL_MODULE_STATE afxModuleS
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()
AFX_MODULE_STATE* pModuleState =
&afxModuleS
return pModuleS
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
return pModuleS
AfxGetAppModuleState
AfxGetAppModuleState是最简单的,直接返回_afxBaseModuleState:
AFX_MODULE_STATE* AFXAPI AfxGetAppModuleState()
return _afxBaseModuleState.GetData();
从上面的讨论可以看出,当前处于那个MFC Module的状态之中,返回的就是那个MFC
Module所相关联的CWinApp对象。如果你有多个Module都是动态链接到MFC
DLL的话,那么AfxGetAppModuleState返回的总是同一个CWinApp。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。2238人阅读
c++(176)
本技术备忘录介绍MFC &模块状态&结构的实现。充分理解模块状态这个概念对于在DLL中使用MFC的共享动态库是十分重要的。
MFC的状态信息分为三种:全局模块状态数据、进程局部状态数据和线程局部状态数据。有时这些数据类型之间没有严格界限,例如MFC的句柄表既是全局模块状态数据也属于线程局部状态数据。
进程局部状态数据和线程局部状态数据差不多。早先这些数据是全局的,但是为了更好的支持Win32和多线程,现在设计成进程或者线程相关的。模块状态数据既可以包含真正的全局状态数据,也可以指向进程或者线程相关的数据。
一、什么是模块状态?
模块状态实际上是指可执行模块运行所需的一个数据结构。首先要说明,这里的"模块"指的是一个MFC可执行程序,或者使用共享版本MFC动态库的DLL或者ActiveX控件。没有使用MFC的程序或者DLL等不在讨论范围之内。
正如下图"单个模块的状态数据"所描述的,使用MFC的每个模块都有一套状态数据。这些数据包括包括:窗口进程句柄(用于加载资源),指向当前程序的CWinApp和CWinThread对象的指针,OLE模块引用次数,以及很多关于Windows对象和其对应句柄的映射表等等。
&&&&&&&&&&&&&&&& 单个模块(程序)的状态数据&&&&&&&&&&&&&& &&&&&&&&&&&& +-------------MFC程序&&&&&&&&&&&& |&&&&&&&&&&& //&&&&&& +--------------------------------------------+&&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |&&&&&& |&&& +--------------------------------+&&&&& |&&&&&& |&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |&&&&& |&&&&&& |&&& |&& 线程对象&&&&&&&&&&&&&&&&&&&& |&&&&& |&&&&&& |&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |&&&&& |&&&&&& |&&& +--------------------------------+&&&&& |&&&&&& |&&& |& m_pModuleState&&&&&&&&&&&&&&& +---+& |&&&&&& |&&& +--------------------------------+&& |& |&&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //& |&&&&&& +--------------------------------------------+&&&&&& |&&& 状态数据&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |&&&&&& +--------------------------------------------+
(注意,因为采用的字符画图,如果图形显示有问题,请复制到记事本中看)
一个模块的所有状态数据包含在一个结构中,这个结构在MFC中被打包成一个类 AFX_MODULE_STATE, 它派生自 CNoTrackObject。关于这个类后面会谈到。AFX_MODULE_STATE类的定义位于AfxStat_.H中。内容如下所示:
// AFX_MODULE_STATE (模块的全局数据)class AFX_MODULE_STATE : public CNoTrackObject{public:&//构造函数#ifdef _AFXDLL&AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD dwVersion);&AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD dwVersion,&&BOOL bSystem);#else&AFX_MODULE_STATE(BOOL bDLL);#endif&~AFX_MODULE_STATE(); &&&//析构函数
&CWinApp* m_pCurrentWinA&&//指向CWinApp对象的指针&HINSTANCE m_hCurrentInstanceH&//当前进程句柄&HINSTANCE m_hCurrentResourceH&//当前资源句柄&LPCTSTR m_lpszCurrentAppN&&//当前程序的文件名&BYTE m_bDLL;&&& &&&//TRUE表示模块是 DLL,否则是EXE&BYTE m_bS &&&//TRUE表示模块是系统模块。&BYTE m_bReserved[2]; &&&//字节对齐
&DWORD m_fRegisteredC &&//窗口类注册标记
&。。。//很多其它运行态数据};
二、为什么需要切换模块状态
模块状态数据是十分重要的。因为很多MFC函数都要使用这些状态数据。如果一个MFC程序使用多模块,比如一个MFC程序需要调用多个DLL或者OLE控件的情况,则每个模块都拥有自己的一套MFC状态数据。
MFC程序运行过程中,每个线程都包含一个指向&当前&或者&有效&模块状态的指针(自然,这个指针是MFC的线程局部状态数据的一部分)。当线程执行代码流跨越模块边界,转入一个特定的模块的时候,就要改变这个指针的值,如下图所示,m_pModuleState必须设置成指向有效的模块状态数据。这一点是非常重要的,否则将导致无法预知的程序错误。
多模块下的状态数据
&MFC程序 && /&&& /&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +--------------+&+--------------------------------------+&&&&&&&& |&& DLL模块1&& |&|&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |&&&&&&&& |&&&&&&&&&&&&& |&|&& +----------------+&&&&& 转向模块1& |&&&&&&&& +--------------+&|&& |&& 线程对象&&&& |&&&& +-----------+--------&|& 状态数据&&& |&|&& |&&&&&&&&&&&&&&& |&&&& |&&&&&&&&&& |&&&&&&&& +--------------+&|&& +----------------+&&&& |&&&&&&&&&& |&|&& | m_pModuleState +-----+&&&&&&&&&& |&&&&&&&& +--------------+&|&& |&&&&&&&&&&&&&&& |&&&&& 转向模块2& |&&&&&&&& |&& DLL模块2&& |& &|&& |&&&&&&&&&&&&&&& +-----------------+----+&&& |&&&&&&&&&&&&& |& &|&& +----------------+&&&&&&&&&&&&&&&& |&&& |&&& +--------------+&|&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |&&& +---&|& 状态数据&&& |&+--------------------------------------+&&&&&&&& +--------------+&|&& 状态数据&&&&&&&&&&&&&&&&&&&&&&&&&& |&+--------------------------------------+
(注意,因为采用的字符画图,如果图形显示有问题,请复制到记事本中看)
比如说,如果你在DLL中导出了一个函数,该函数要创建一个对话框,而这个对话框的模板资源位于DLL中。缺省情况下,MFC是使用主程序中的资源句柄来加载资源的,但现在这个对话框的资源位于DLL中,所以,必须设置m_pModuleState指向DLL模块的状态数据,否则,就会导致加载资源失败。
因此,每个模块要负责在它的所有入口点进行状态数据的切换。所谓"入口点" 就是任何执行代码流可以进入模块的地方,包括: 1、DLL中导出的函数;2、COM接口函数3、窗口过程
首先谈dll中的导出函数。一般来说,如果从一个DLL中导出了一个函数,应该使用AFX_MANAGE_STATE 宏维护正确的全局状态。
调用这个宏的时候,它设置pModuleState指向有效的模块状态数据,从而该函数后面的代码就可以通过该指针得到有效的状态数据。当函数执行完毕,即将返回时,该宏将自动恢复指针原来的值。
这个自动切换是这样完成的,在栈空间上创建一个AFX_MODULE_STATE类的实例,并把当前的模块状态指针保存在一个成员变量里面,然后把pModuleState设置成有效的模块状态,在这个实例对象的析构函数中,对象恢复以前保存的指针。
所以,对于上面所说的DLL导出函数,可以在该函数的开始加入如下预句:
AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
这个代码将当前的模块状态设置成AfxGetStaticModuleState返回的值。离开当前作用域之后恢复原来的模块状态。
但是,不是任何DLL中导出的函数都需要使用AFX_MANAGE_STATE。例如InitInstance函数,MFC在调用这个函数的时候是自动切换模块状态的。对于MFC常规动态库中的所有消息处理函数来说也不需要使用这个宏。因为常规DLL会链接一个特殊的主窗口过程,里面会自动切换模块状态。对于其它导出函数,如果没有用到模块状态中的数据,也可以不使用这个宏。
对于COM接口的成员函数来说,一般使用METHOD_PROLOGUE宏来维护正确的模块状态数据。这个宏实际上也使用了AFX_MANAGE_STATE。详细信息可以参考技术备忘录38:"MFC/OLE IUnknown的实现"。
对于窗口过程,如果模块使用了MFC,则该模块会静态链接一个特殊的窗口过程实现函数,首先用AFX_MANAGE_STATE宏设置有效的模块状态,然后调用AfxWndProc,这个函数接着调用某窗口具体的WindowProc函数。具体可以参考WINCORE.CPP。
三、模块状态是如何切换的
一般来说,设置当前的模块状态数据可以通过函数AfxSetModuleState。但是大多数情况下,无需直接使用这个API函数,MFC知道应该如何正确设置模块状态数据,它会替你调用它,比如在WinMain函数、OLE入口、AfxWndProc中等等。这是通过静态链接一个特殊的WndProc和WinMain (或者DllMain)实现的。可以参考 DLLMODUL.CPP或者APPMODUL.CPP,找到这些实现代码。
设置当前的模块状态,而又不把它设置回去的情况是十分少见的,一般来讲,在改变了模块状态后,都要进行恢复。可以通过AFX_MANAGE_STATE宏和AFX_MAINTAIN_STATE类来实现。我们看看这个宏的定义:
#ifdef _AFXDLL&//定义了这个符号表示动态链接MFCstruct AFX_MAINTAIN_STATE{&AFX_MAINTAIN_STATE(AFX_MODULE_STATE* pModuleState);//参数是AFX_MODULE_STATE类对象指针&~AFX_MAINTAIN_STATE();
protected:&AFX_MODULE_STATE* m_pPrevModuleS&&//保存在这个私有变量中};
class _AFX_THREAD_STATE;&//线程局部状态数据,这个类也是派生自CNoTrackObjectstruct AFX_MAINTAIN_STATE2&&&&//多线程版本{&AFX_MAINTAIN_STATE2(AFX_MODULE_STATE* pModuleState);&~AFX_MAINTAIN_STATE2();
protected:&AFX_MODULE_STATE* m_pPrevModuleS&&//用来保存模块状态数据的指针&_AFX_THREAD_STATE* m_pThreadS&&//指向线程局部状态数据的指针};#define AFX_MANAGE_STATE(p) AFX_MAINTAIN_STATE2 _ctlState(p);&//定义AFX_MANAGE_STATE宏#else& // _AFXDLL#define AFX_MANAGE_STATE(p)&//否则,这个宏没有意义。#endif //!_AFXDLL
我们再来看看AFX_MAINTAIN_STATE2的构造函数,很简单的代码:
AFX_MAINTAIN_STATE2::AFX_MAINTAIN_STATE2(AFX_MODULE_STATE* pNewState){&m_pThreadState = _afxThreadS&&//首先保存线程局部状态数据指针&m_pPrevModuleState = m_pThreadState-&m_pModuleS //保存全局模块状态数据指针&m_pThreadState-&m_pModuleState = pNewS&//设置全局模块状态数据指针,指向pNewState。}
由此可见,线程局部状态数据里面包含一个指向全局模块状态数据的指针。
四、进程局部数据
对于Win32 DLL,在每个关联它的进程中都有一份独立的数据拷贝。考虑如下代码:
static CString strG // at file scope
__declspec(dllexport) void SetGlobalString(LPCTSTR lpsz){&& strGlobal =}
__declspec(dllexport)void GetGlobalString(LPCTSTR lpsz, int cb){&& lstrcpyn(lpsz, strGlobal, cb);}
如果上述代码位于一个DLL中,并且该DLL被两个进程A和B加载(或者同一个程序的两个实例),那么将会发生什么事情呢? A调用SetGlobalString("Hello from A"),结果,在进程A的上下文中为该CString对象分配内存空间,现在B 调用GetGlobalString(sz, sizeof(sz))。那么B是否可以访问到A 设置的数据呢?
在WIN3.1中是可以的,因为Win32s没有提供象Win32那样的进程间的保护措施。显然这是有问题的,为了解决这个问题。MFC 3.x 是采用线程局部存储(TLS)技术解决这个问题,和Win32下保存线程局部数据的方法类似。但是每个MFC DLL都要在每个进程中使用两个TLS索引,如果加载过多DLL,会很快消耗完TLS索引(只有64个)。除此以外,还有其它问题。所以在MFC 4.x的版本中,采用了一套模板类,来包装这些进程相关的数据。例如下面的方法:
struct CMyGlobalData : public CNoTrackObject{&& CString strG};CProcessLocal&CMyGlobalData& globalD
__declspec(dllexport) void SetGlobalString(LPCTSTR lpsz){&& globalData-&strGlobal =}
__declspec(dllexport)void GetGlobalString(LPCTSTR lpsz, int cb){&& lstrcpyn(lpsz, globalData-&strGlobal, cb);}
MFC采用两个步骤实现该方法。首先,在Win32 Tls* API (包括TlsAlloc, TlsSetValue, TlsGetValue等)之上实现一个接口层,无论进程加载多少DLL,每个进程仅需使用两个TLS索引。其次,通过CProcessLocal模板访问数据,它重载了-&操作符。所有打包进CProcessLocal的对象必须派生自CNoTrackObject。而 CNoTrackObject提供一个底层的内存分配函数(LocalAlloc/LocalFree)以及一个虚析构函数,保证进程终止的时候,MFC可以自动销毁该进程局部数据。这些CNoTrackObject派生类对象可以有自己的析构函数,用于其它必要的清除操作。上面的例子里面没有,因为编译器会自动产生一个,并销毁内嵌的 CString 对象。CNoTrackObject类的定义位于Afxtls_.h中,主要是重载new 和 delete操作符,它的实现位于Afxtls.cpp中。
五、线程局部数据
和进程局部数据类似,线程局部数据是指必须和指定线程相关的局部数据,也就是说,不同线程访问同一个数据的时候,要为每个线程准备一份数据的实例。假设有一个CString对象,可以通过把它嵌入 CThreadLocal模板,使它成为线程局部数据:
struct CMyThreadData : public CNoTrackObject{&& CString strT};CThreadLocal&CMyThreadData& threadD
void MakeRandomString(){&& // 一种洗牌方式,52张牌,效率很低,不实用&& CString& str = threadData-&strT&& str.Empty();&& while (str.GetLength() != 52)&& {&&&&& TCHAR ch = rand() % 52 + 1;&&&&& if (str.Find(ch) & 0)&&&&&&&& str += && }}
如果从两个不同的线程调用 MakeRandomString ,则每个线程都会打乱字符串的顺序,而且相互之间没有影响。这是因为每个线程都有一个strThread实例对象,而不是只有一个全局对象。
上述代码中使用了一个引用,而不是在循环中使用 threadData-&strThread,避免循环调用-&操作符,这样可以提高代码的效率。
-------------------End. iwaswzq
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:699930次
积分:7239
积分:7239
排名:第2403名
原创:55篇
转载:234篇
评论:115条
(2)(1)(1)(1)(1)(1)(1)(3)(9)(1)(3)(5)(9)(11)(32)(5)(2)(5)(2)(4)(1)(1)(1)(3)(16)(10)(15)(18)(25)(2)(6)(7)(10)(3)(13)(4)(1)(5)(3)(3)(3)(4)(5)(3)(7)(13)(6)(1)(1)

我要回帖

更多关于 通达信 交易模块 的文章

 

随机推荐