全文预览已结束
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
用MFC实现多线程当使分开的任务并发执行能够带来性能的提升时,你可以在你的应用程序中使用多线程。例如:考虑一个文字处理软件,它每5分钟备份一次当前的文档。用户经应用程序主窗口到文档的输入由主线程处理。应用程序代码可以创建一个分开的线程来负责安排和执行自动备份。建立一个辅线程可以防止对较长文档的备份工作影响用户界面的响应能力。使用多线程可以为你的应用程序带来性能上的增益的情况包括:排班(时间驱动)的活动 文字处理软件例子中执行自动备份特性的线程在5分钟间隔内被阻塞。在Win32应用程序中,线程排班可以被设置到毫秒精度。事件驱动的活动 线程可以被来自其它线程的信号触发。举一个监视系统的例子:记录错误的线程通常处于非活动状态,直到其它线程通知它某种错误发生时才活动。分布式的活动 当数据必须从多个计算机收集(或派发给多个计算机)时,倾向于为每个请求创建一个线程以便它们可以并行处理,且处于它们自己的时间框架内。区分优先次序的活动 Win32线程可以被赋予一个优先级来决定由线程排班程序分配给它的运行时间的比例。有时,为了提高程序的响应能力,将它所要做的工作分为一个高优先级的线程来处理用户界面和一个低优先级的线程来处理后台工作将会很有用。MFC的多线程:CWinThread类在MFC中所有的线程都由CWinThread对象来表现,包括你的应用程序的主线程。主线程由一个起源于CWinApp的类实现,而CWinApp直接起源于CWinThread。虽然Win32 API提供了_beginthreadex函数,可以让你在底层启动线程,但是,你应该总是使用CWinThread类来创建那些需要使用MFC功能的线程。这是因为CWinThread类使用线程本地存储来管理在MFC环境中的线程的上下文信息。你可以直接声明CWinThread对象,但在许多情况下,你将让MFC全局函数AfxBeginThread()来为你创建一个CWinThread对象。CWinThread:CreateThread()函数用来启动新的线程。CWinThread类也提供了SuspendThread()和ResumeThread()函数以便你挂起和恢复线程的执行。工作线程和用户界面线程MFC区别两种线程:工作线程和用户界面线程。这种区分是由MFC自己进行的,Win32 API不区分线程的种类。工作线程一般用来完成那些不需要用户输入的后台任务。可举的例子包括数据库备份功能和网络联接状态监视功能。用户界面线程能够处理用户输入,它们通过实现消息循环来响应那些由用户与应用程序交互所产生的事件和消息。用户界面线程的最好的例子是你的应用程序中由源自CWinApp的类所表现的主线程。辅助的用户界面线程可以提供一种方法,使得与应用程序的交互不会降低其它应用特性的性能。例如,考虑一个可以让麻醉师监视手术中的病人情况的应用程序。一个用户界面线程可以使麻醉师进入他管理的麻药的细节,而不至于打断用于监视病人生命状况的线程。你通过在MFC应用程序中调用全局函数AfxBeginThread()来创建辅线程。AfxBeginThread()有两种重载的形式,一种用来创建工作线程,另一种用来创建用户界面线程。下面的部分将演示如何使用这两种形式。建立工作线程建立一个工作线程只是简单的实现一个控制函数并将其地址传给适当的形式的AfxBeginThread()函数的问题,这个控制函数执行你的线程所要执行的内容。控制函数应具有下面的语法格式:UINT MyControllingFunction(LPVOID pParam);其中的参数是一个单一的32位值,它可以用于许多用途,也可以被忽略。它可以给函数传递一个简单的值,也可以传递一个含有多个参数的结构的指针。如果该参数设计一个结构,那么这个结构不仅能用来从调用者向线程传送数据,也可以用来将数据从线程传送会调用者。工作线程形式的AfxBeginThread()是这样声明的:CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);前两个参数是控制函数的地址和要传送给控制函数的参数。其余的参数(它们都有默认值)可以让你指定线程的优先级、栈大小、创建后是立即挂起还是立即运行。最后的参数允许你指定线程的安全属性-默认值NULL表示该线程将继承调用线程的安全属性。AfxBeginThread()创建一个新的CWinThread类,调用其CreateThread()函数来启动新线程,并返回该线程的指针。贯穿整个过程的检查保证如果创建中的任何一步失败,所有对象都将被正确释放。为了结束该线程,你可以在该线程中调用全局函数AfxEndThread()或只是简单的从控制函数返回。控制函数的返回值一般被用来指示终止的原因。传统上,如果函数成功,退出代码为0。非零值用来指示指定类型的错误。建立用户界面线程正如我们前面所提到的,MFC应用程序中的所有线程都由CWinThread类表现,这个类由AfxBeginThread()函数创建。当你创建一个工作线程时,AfxBeginThread()为你创建一个一般的CWinThread对象,并将你的控制函数的地址赋给CWinThread:m_pfnThreadProc成员变量。为了建立一个用户界面线程,你必从CWinThread引出你自己的类,并将该类的运行时信息传给用户界面形式的AfxBeginThread()。下面摘自MFC源代码的片断展示了框架如何区分工作线程和用户界面线程。代码摘自_AfxThreadEntry(),所有MFC线程的入口点。/ First - check for simple worker threadDWORD nResult = 0;if (pThread-m_pfnThreadProc != NULL) nResult = (*pThread-m_pfnThreadProc)(pThread-m_pThreadParams ); ASSERT_VALID(pThread);/ Else - check for thread with message loopelse if (!pThread-InitInstance() ASSERT_VALID(pThread); nResult = pThread-ExitInstance();else / will stop after PostQuitMessage called ASSERT_VALID(pThread); nResult = pThread-Run();/ Clean up and shut down the threadthreadWnd.Detach();AfxEndThread(nResult);如果m_pfnThreadProc指向一个控制线程,代码便知道它正在处理一个工作线程。控制线程被调用后线程被终止。如果m_pfnThreadProc为NULL,该函数假定它正在处理一个用户界面线程。于是调用该线程对象的InitInstance()函数进行线程的初始化-例如,建立主窗口和其它的用户界面对象。如果InitInstance()成功返回(即返回TRUE),Run()函数被调用。CWinThread:Run()实现一个消息循环来处理有该线程主窗口的消息。InitInstance()和Run()函数你应该听起来很熟悉。它们是CWinApp继承的两个关键的虚函数。你被责成为你的线程类提供一个重载的InitInstance()。你经常要提供一个针对一个类的重载的CWinThread:ExitInstance()作为清除函数。通常你将使用基类的Run()函数。线程同步辅线程通常用来实现异步处理。一个异步操作是一个不依赖于其它事件或活动的执行。考虑我们的定时器线程,它运行在自己的执行路径上,每秒检查一次系统时钟。它不需要等待应用程序主线程中的事件,并且应用程序可以正常进行而不必等待定时器线程完成它的任务。很多情况下这些异步的活动需要同步,或协调它们的操作。例如,考虑一个排队有其它应用程序创建的打印任务线程的打印排班线程。打印任务线程会需要通知调度程序它想加入队列,并且调度程序要给队列中轮到打印的的任务发送消息。另一种典型的需要同步的假设是对应用程序全局数据的更新。考虑一个应用程序,它拥有一个传感器线程,该线程从传感器设备读取数据来更新一个数据结构。另一个线程用来读取该结构并在屏幕上显示其状态图像。现在假设显示线程尝试读取一份数据,而恰恰在这一毫秒,该数据结构正在被传感器线程更新。其结果很可能是被破坏的数据,这将可能导致严重的后果,例如,如果这个应用程序是一个监视核电站的程序。线程对全局数据的访问必须被同步,以保证在任何时刻只有一个线程能够读取或修改该数据。一种实现线程间同步的方法是使用一个全局对象来充当线程间的中间媒体。MFC提供了一组同步类,在表中列出。这些源自CSyncObject的同步类可以被用来协调任何种类的异步事件。表MFC同步类名称 描述CCriticalSection 只允许当前进程中的一个线程访问某个对象的同步类CMutes 只允许系统中一个进程内的一个线程访问某个对象的同步类CSymaphore 只允许一到某个指定数目个线程同时访问某个对象的同步类CEvent 当某个事件发生时通知一个应用程序的同步类这些同步类与同步访问类:CSingleLock和CMultiLock联合使用来提供对全局数据或共享资源的线程安全访问。对这些类的建议的用法如下:将对访问全局数据或资源的函数封装到一个类中。通过使用公有函数来保护受控制的数据和受管制的访问。在你的类中,建立一个适当类型的同步对象。例如,你要使用一个CCriticalSection对象来保证在某个时刻只有一个线程更新你的全局数据;或者,你可能包含一个CEvent对象来表示某个资源已经准备好接受数据。在提供对数据或资源的访问的函数中,创建一个同步访问对象的实例。当你一次需要等待一个对象时使用CSingleLock;当在某个特殊时刻你可以使用多个对象时使用CMultiLock。在函数代码试图访问受保护的数据之前,调用同步访问对象的Lock()成员函数。Lock()函数可以被指明在指定长(或不确定)的时间内等待相关联的对象变得可用。例如,一个CCriticalSection对象在为当前线程获得安全的排外的访问权时将变得可用。一个
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年低空经济产业集群发展路径研究报告
- 2026-2031中国骨科耗材行业发展趋势预测及投资战略咨询报告
- 2025年药店处方审核试题及答案
- 2025人工智能与健康考试题及答案
- 2026-2031中国培训市场前景预测
- 2025高级项目管理试题及答案
- 数据中心机房建设合同
- 汉代书法艺术与社会功能
- 2026年废核污染波污染易发区保护保险合同中
- 药品经营和使用质量监督管理办法考试试题有答案
- 农业机械安全培训资料课件
- 燃气管道压接工艺方案
- 2025年新人教版7年级道德与法治上册全册课件
- 汽车销售员客户跟进技巧培训材料
- 肿瘤培训课件下载
- 太阳能光伏安装规定
- 水利工程水库蓄水工作方案
- 2025年四川省拟任县处级领导干部任职资格试题及参考答案
- 2025年湖北省高考物理真题卷含答案解析
- 质量安全培训课件
- 2025年采购专员考试试题及答案
评论
0/150
提交评论