Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1072469
  • 博文数量: 243
  • 博客积分: 3053
  • 博客等级: 中校
  • 技术积分: 2975
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-02 21:11
文章分类

全部博文(243)

文章存档

2013年(2)

2012年(20)

2011年(5)

2010年(114)

2009年(102)

我的朋友

分类:

2010-12-08 18:24:18

4        模块-线程状态的作用

由模块-线程状态类的定义可知,一个模块-线程状态包含了几类Windows对象—MFC对象的映射。下面讨论它们的作用。

1)      只能访问本线程MFC对象的原因

 MFC规定:

1)不能从一个非MFC线程创建和访问MFC对象

 如果一个线程被创建时没有用到CWinThread对象,比如,直接使用“C”的_beginthread或者_beginthreadex创建的线程,则该线程不能访问MFC对象;换句话说,只有通过CWinThread创建MFC线程对象和Win32线程,才可能在创建的线程中使用MFC对象。

2)一个线程仅仅能访问它所创建的MFC对象

 这两个规定的原因是:

为了防止多个线程并发地访问同一个MFC对象,MFC对象和Windows对象之间有一个一一对应的关系,这种关系以映射的形式保存在创建线程的当前模块的模块-线程状态信息中。当一个线程使用某个MFC对象指针P时,ASSERT_VALID(P)将验证当前线程的当前模块是否有Windows句柄和P对应,即是否创建了P所指的Windows对象,验证失败导致ASSERT断言中断程序的执行。如果一个线程要使用其他线程的Windows对象,则必须传递Windows对象句柄,不能传递MFC对象指针。

当然一般来说,MFC应用程序仅仅在Debug版本下才检查这种映射关系,所以访问其他线程的MFC对象的程序在Realease版本下表面上不会有问题,但是MFC对象被并发访问的后果是不可预见的。

2)      实现MFC对象和Windows对象之间的映射

 MFC提供了几个函数完成MFC对象和Windows对象之间的映射或者解除这种映射关系,以及从MFC对象得到Windows对象或者从Windows对象得到或创建相应的MFC对象。

每一个MFC对象类都有成员函数Attach和Detach,FromHandle和FromHandlePermanent,AssertValid。这些成员函数的形式如下:

Attach(HANDLE Windows_Object_Handle)

 例如:CWnd类的是Attach(HANLDE hWnd),CDC类的是Attach(HDC hDc)。

Attach用来把一个句柄永久性(Perment)地映射到一个MFC对象上:它把一个Windows对象捆绑(Attach)到一个MFC对象上,MFC对象的句柄成员变量赋值为Windows对象句柄,该MFC对象应该已经存在,但是句柄成员变量为空。

Detach()

Detach用来取消Windows对象到MFC对象的永久性映射。如果该Windows对象有一个临时的映射存在,则Detach不理会它。MFC让线程的Idle清除临时映射和临时MFC对象。

FromHandle(HANDLE Windows_Object)

 它是一个静态成员函数。如果该Windows对象没有映射到一个MFC对象,FromHandle则创建一个临时的MFC对象,并把Windows对象映射到临时的MFC对象上,然后返回临时MFC对象。

FromHandlePermanent(HANDLE Windows_Object)

它是一个静态成员函数。如果该Windows对象没有永久地映射到一个MFC对象上,则返回NULL,否则返回对应的MFC对象。

AssertValid()

 它是从CObject类继承来的虚拟函数。MFC覆盖该函数,实现了至少一个功能:判断当前MFC对象的指针this是否映射到一个对应的可靠的Windows对象。

图 9-9示意了MFC对映射结构的实现层次,对图9-9解释如下。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

图中上面的虚线框表示使用映射关系的高层调用,包括上面讲述的几类函数。MFC和应用程序通过它们创建、销毁、使用映射关系。

图中中间的虚线框表示MFC使用CHandleMap类实现对映射关系的管理。一个CHandleMap对象可以通过两个成员变量来管理两种映射数据:临时映射和永久映射。模块-线程状态给每一类MFC对象分派一个CHandleMap对象来管理其映射数据(见模块-线程类的定义),例如m_pmapHWND所指对象用来保存CWnd对象(或派生类对象)和Windows window之间的映射。

下面的虚线框表示映射关系的最底层实现,MFC使用通用类CMapPtrToPtr来管理MFC对象指针和Windows句柄之间的映射数据。

对本节总结如下:

1)      MFC的映射数据保存在模块-线程状态中,是线程和模块局部的。每个线程管理自己映射的数据,其他线程不能访问到本线程的映射数据,也就不允许使用本线程的MFC对象。

 

2)      每一个MFC对象类(CWnd、CDC等)负责创建或者管理这类线程-模块状态的对应CHandleMap类对象。例如,CWnd::Attach创建一个永久性的映射保存在m_pmapHwnd所指对象中,如果m_pmapHand还没有创建,则使用AfxMapHWND创建相应的CHandleMap对象。

3)      映射分两类:永久性的或者临时的。

 

 

阅读(1370) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~