ImageVerifierCode 换一换
格式:DOC , 页数:4 ,大小:49.50KB ,
资源ID:966520      下载积分:5 文钱
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,省得不是一点点
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.wenke99.com/d-966520.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(预留内存携带附加信息的设计.DOC)为本站会员(天***)主动上传,文客久久仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知文客久久(发送邮件至hr@wenke99.com或直接QQ联系客服),我们立即给予删除!

预留内存携带附加信息的设计.DOC

1、预留内存携带附加信息的设计有时候,将数据与一个对象的实例关联起来是很有帮助的。这种设计要求预留一定的内存,一倍特定附加数据的存储。通过调用 SetWindowWord 或 SetWindowLong 函数将数据与一个指定的窗口关联起来,数据保存在窗口附加内存块中。窗口内存块即是一种窗口对象(HWND)的附加数据(window extra bytes),参考WNDCLASS.cbWndExtra 字段(Specifies the number of extra bytes to allocate following the window instance.)。这种预留附加的设计,在 MFC 中处

2、处可见。对于下拉选择列表(CComboBox)、下拉列表框、列表视图和树控件,我们不光希望其能显示条目内容(item text),还希望每个条目能够携带附加信息,即存储额外的关联数据(item data),以备不时之需。这四个控件都提供了SetItemData/GetItemData 接口,供用户储存关联数据。存储的数据为DWORD 值类型,可以是简单的数值,也可以存储指针。线程消息队列和_ptiddata我们在编写第一个 SDK 窗口程序时,就接触到了消息这一重要概念。实际上,消息队列是一种线程私有数据,每一个 Windows 程序的 UI(CUI/GUI)线程都维持了一个消息队列。GetM

3、essage、TranslateMessage、DispatchMessage 等对消息的操作都是与调用线程的消息队列息息相关。PostThreadMessage 是线程消息投递函数,它向一个指定 ID( idThread)的线程发送一条消息,然后不等处理立即返回。这个 API 在多线程架构程序中非常有用。 PostQuitMessage 是结束线程运行,相当于 nExitCode 作为 WM_QUIT 消息参数调用PostThreadMessage。调用线程收到该消息后即 ExitThread,故该函数一般用来响应 WM_DESTROY 消息。尽管秉持封装的原则,我们极力强调避免使用全局变量

4、,但全局变量对于进程级和线程级的系统统筹管理却是非常有用。除了消息队列这种系统内置的线程私有数据外,Windows 提供了线程局部存储系统( TLS,Thread Local Storage),为用户提供了存储与线程关联数据的接口。前面提到的_beginthreadex 中分配的 _ptiddata(pointer to per-thread data),即使用了 TLS。_ptiddata 为 Windows 平台的多线程程序中,strtok、strerror(errno)等依赖全局变量或静态变量的 CRT 函数的实现提供了有效的解决方案。Win32 线程局部存储系统用于管理 TLS 的数据

5、结构是很简单的,Windows 仅为系统中的每一个进程维护一个位数组,再为该进程中的每一个线程申请一个同样长度的数组空间,如下图所示。在 Windbg 中,可以窥探 TEB 中的 TLS 数据结构。lkd dt _tebnt!_TEB+0x02c ThreadLocalStoragePointer : Ptr32 Void+0xe10 TlsSlots : 64 Ptr32 Void+0xf10 TlsLinks : _LIST_ENTRY+0xf94 TlsExpansionSlots : Ptr32 Ptr32 Voidtypedef struct _TEB / 66 elements,

6、0xFB8 bytes (sizeof)/ /*0x02C*/ VOID* ThreadLocalStoragePointer;/ /*0xE10*/ VOID* TlsSlots64;/*0xF10*/ struct _LIST_ENTRY TlsLinks; / 2 elements, 0x8 bytes (sizeof)/ /*0xF94*/ VOID* TlsExpansionSlots;/ TEB, *PTEB;当一个线程被创建时,Windows 就会在进程地址空间中为该线程分配一个长度为 TLS_MINIMUM_AVAILABLE 的数组,数组成员的值都被初始化为 0。在内部,系统

7、将此数组与该线程关联起来,保证只能在该线程中访问此数组中的数据。如上图所示,每个线程都有它自己的数组,数组成员可以存储任何数据。运行在系统中的每一个进程都有上图所示的一个位数组。位数组的成员是一个标志,每个标志的值被设为 FREE 或 INUSE,指示了此标志对应的数组索引是否在使用中。Windows 保证至少有 TLS_MINIMUM_AVAILABLE(定义在 WinNT.h 文件中)个标志位可用。动态使用 TLS 典型步骤如下。(1)主线程调用 TlsAlloc 函数为线程局部存储分配索引,函数原型如下。DWORD TlsAlloc(VOID);TlsAlloc 为我们预订了一个索引。如

8、果 TlsAlloc 返回的索引为 3,那等于说索引 3 已经被我们预订了,无论是进程中当前正在运行的线程,还是今后可能会创建的线程,都不能再使用索引 3。(2)每个线程调用 TlsSetValue 和 TlsGetValue 设置或读取线程数组中的值,这两个函数的原型如下。BOOL TlsSetValue(DWORD dwTlsIndex, / TLS indexLPVOID lpTlsValue / value to store);LPVOID TlsGetValue(DWORD dwTlsIndex / TLS index);(3)主线程调用 TlsFree 释放局部存储索引。函数的惟一

9、参数是TlsAlloc 返回的索引。BOOL TlsFree(DWORD dwTlsIndex / TLS index);MFC 中的线程局部存储如果你需要大量的数据贯穿一个线程,普通的 TLS 索引一个值就会变得不实用,Windows 的 TLS 只允许用户保存一个 32 位的指针。如果需要用户保存任意类型的数据(包含整个类)。这个任意大小的数据所占的内存通常是在进程的堆中分配,所以当用户释放全局索引时,系统必须将每个线程内此数据占用的内存释放掉,这就要求系统把为各线程分配的内存都记录下来。较好的方法是将各个私有数据的首地址用一个链表连在一起,释放全局索引时只要遍历此链表,就可以逐个释放线程

10、私有数据占用的空间了。例如,有下面一个存放线程私有数据的数据结构。struct CThreadDataCThreadData* pNext; / 指向下一个线程的 CThreadData 结构的指针LPVOID pData; / 指向真正的线程私有数据的指针;指针 pData 指向为线程分配的内存的首地址,指针 pNext 将各线程的数据连在了一起。这实际上是一种二级指针的分槽存储。MFC 的线程局部存储类CThreadLocal 即实现了二级指针的分槽存储。MFC 框架的状态信息也是理解的难点,包括模块状态AFX_MODULE_STATE、线程状态 _AFX_THREAD_STATE 和模块

11、线程状态AFX_MODULE_THREAD_STATE。这些线程级别的全局状态维持即使用了线程局部存储(TLS )。参考李久进著作的MFC 深入浅出第九章MFC 的状态。由于 MFC 广泛地应用了线程局部存储,故在 MFC 下,使用线程必须格外小心。许多 MFC 对象仅在创建它们的线程内运作。一般地,具有句柄映射的任何对象都不能从其他线程访问该对象。例如,模块线程状态AFX_MODULE_THREAD_STATE 中的 CHandleMap* m_pmapHWND 映射记录了MFC 线程中创建的 CWnd 对象实例与内核窗口句柄(HWND)之间的映射消息。内核窗口句柄是可以进程访问级别,因此可

12、跨线程访问。但是试图传递 CWnd对象实例以期跨线程操作,往往失败。因为另一个引用线程并未像创建线程那样维系一个映射,所以当需要 CWndHWND 以执行 API 操作时,往往找不到其所指窗口。针对以上问题,通常优先传送句柄,避免在线程之间传送 MFC 对象。在引用线程中将其转换为临时 MFC 对象。例如,假设线程 A 创建一个 CWnd 对象。线程 A 并不将对象传送给线程 B,而将该对象的 m_hWnd 成员传送给线程 B。于是,线程 B 可以调用 CWnd:FromHandle,以创建一个临时的 CWnd 对象。如果线程 B 需要更持久的连接,就可以使用 Attach 方法,在窗口及其 CWnd对象之间建立持久的关联。另外的一个常见问题是 MFC 对象访存的线程安全性问题。MFC 对象不会自动在不同的线程之间做出判断。所以,如果两个线程试图同时访问同一个CString 类的对象,结果可能受到严重破坏。只有防止来自有冲突的 MFC 对象的线程。通常,这将需要使用前面提到的同步机制,以保证多线程数据交换的一致性。

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。