C++课件第16章多任务与多线程编程.ppt
《C++课件第16章多任务与多线程编程.ppt》由会员分享,可在线阅读,更多相关《C++课件第16章多任务与多线程编程.ppt(86页珍藏版)》请在三一办公上搜索。
1、第16章 多任务与多线程编程,C+高级编程,本章主要教学内容,进程与线程线程的种类与MFC同步类线程的使用线程的同步及常用的同步对象,第16章 多任务与多线程编程,16.1 程序、进程和线程概述16.2 线程的种类16.3 线程的创建、启动和终止16.4 线程的操作和管理16.5 在VC+环境中使用同步对象16.6 本章小结16.7 思考与练习,16.1 程序、进程和线程概述,16.1.1 多任务、进程和线程,1Windows3.x的协同多任务,如何解决后台工作和对用户的随时响应之间的协同?详见教材P27。,Windows3.x对应用程序的CPU控制权的调度方式:协同式多任务。其特点详见教材P
2、27。,补充知识:什么是模态对话框和非模态对话框?见附带文件1。,16.Windows95/NT的抢先式多任务,Windows95/NT对应用程序的CPU控制权的 调度方式:抢先式多任务。其特点详见教材P28。,16.1.1 多任务、进程和线程,3进程与线程,16.1.1 多任务、进程和线程,进程由私有虚拟地址空间、代码、数据和其它操作系统资源(如进程创建的文件、同步对象等)组成。,进程就是应用程序的运行实例。,1)什么是进程?,一个应用程序可以运行一个或多个进程。多任务就是指操作系统可以同时运行多个进程。,16.1.1 多任务、进程和线程,2)什么是线程?,一个线程可以执行程序的任意部分的代
3、码,即使这部分代码被另一个线程并发地执行。,线程是Windows95/NT操作系统分时调度中分配CPU时间的基本单位。,一个进程可以有一个或多个线程,其中一个是主线程。,一个进程的所有线程共享它的虚拟地址空间、全局变量和操作系统资源。,16.1.1 多任务、进程和线程,3)进程与线程的关系?,16.2 线程的种类,线程有两种,用户界面线程,工作者线程,MFC应用程序通过调用AfxBeginThread函数并给定不同的参数来自动创建两种线程,而不需要程序自己创建,AfxBeginThread函数的具体说明在中。,16.16.1 MFC中的线程类,1.MFC应用程序中的线程可由对象CWinThre
4、ad表示,CWinThread类派生自CcmdTarget类;,16.CWinThread对象代表在一个应用程序内运行的线程;,3.CWinThread对象允许一个应用程序拥有多个线程;,4.CWinThread对象支持两种线程类型:用户界面线程和工作者线程;,16.16.1 MFC中的线程类,5.用户界面线程可以由CWinThread类派生,也可以是CWinApp类或其派生类。但为安全起见,应由CWinThread类派生。,6.任何使用MFC的线程必须由MFC创建,创建一个线程必须调用AfxBeginThread函数。,7.CWinThread类的数据成员即成员函数见表2-1。,16.16.
5、2 用户界面线程(UI),1)用户界面线程拥有自己的消息循环来处理界面消息,具有收发消息的功能,处理从消息队列取得的消息;,2)用户界面线程通常要与用户交互;,3)用户界面线程可由CWinApp类派生(注:CWinApp类由CWinThread类派生),也可以由CWinThread类直接派生。,4)一个应用程序的主线程通常由CWinApp类派生,主线程应该是用户界面线程。,16.16.3 工作者线程,1)工作者线程没有自己的消息循环,一般用来完成后台的工作,如后台计算、打印、与其它设备的串行数据通信等,这些工作的共同特点就是耗时。,2)为了不影响主线程与用户的交互,通常耗时的工作交给工作者线程
6、来完成;,3)工作者线程可由CWinThread类直接派生。,16.3 线程的创建、启动和终止,16.3.1 线程的创建,线程的创建由AfxBeginThread函数完成。,AfxBeginThread函数有两种调用格式,可以根据需要分别用来创建工作者线程和用户界面线程。,一、AfxBeginThread函数用来创建工作者线程的调用格式:,16.3.1 线程的创建,CWinThread*AfxBeginThread(AFX_THREADPROC pfnThreadProc,LPVOID pParam,int nPriority=THREAD_PRIORITY_NORMAL,UINT nStac
7、kSize=0,DWORD dwCreateFlags=0,LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);,pfnThreadProc:线程函数的地址,该参数不能设置为NULL,线程函数必须定义成全局函数或者类的静态成员函数。,例如:UINT myThreadFunc(LPVOID lparam)或者class Apublic:static UINT _stdcall myThreadFunc(LPVOID lparam);,1.参数说明:,16.3.1 线程的创建,pParam:要传递给线程函数的参数;,nPriority:要启动的线程的优先级,默认
8、优先级为THREAD_PRIORITY_NORMAL(普通优先级),关于线程优先级的详细说明见;,nStackSize:新线程的堆栈大小,如果设置为0,则使用默认大小,在应用程序中一般情况下线程的默认堆栈大小为1M;,16.3.1 线程的创建,lpSecurityAttrs:指向SECURITY_ATTRIBUTES结构的指针,结构中指定了线程的安全属性。如果为NULL,则与创建它的线程的安全属性相同。,dwCreateFlags:线程创建标志,该参数指定线程的初始状态,它可以被指定为下列标志:0:线程在创建后立即执行 CREATE_SUSPENDED:线程在创建后立即挂起,16.3.1 线程
9、的创建,16.函数返回值的说明:,函数AfxBeginThread返回指向CWinThread类的指针。,16.3.1 线程的创建,3.创建工作者线程的过程:,利用函数AfxBeginThread创建工作者线程需要两步:,1)编写线程控制函数;,2)调用函数AfxBeginThread启动线程,将线程控制函数的地址作为第一个参数,线程控制函数的参数作为第二个参数赋给AfxBeginThread函数,,16.3.1 线程的创建,在应用程序中,可以创建一个指向CWinThread类的指针,用来保存AfxBeginThread函数的返回值,即AfxBeginThread函数创建成功的线程类CWinT
10、hread,以便创建好的线程进行控制,例如:,4.其它说明:,16.3.1 线程的创建,CWinThread*pWinThread;pWinThread=AfxBeginThread(ControlFunction,pParam,THREAD_PRIORTY_NORMAL,0,CREATE_SUSPENDED,NULL);,16.3.1 线程的创建,pWinThread-m_bAutoDelete=false;delete pWinThread;,这时应注意:,即要将CWinThread类的数据成员m_bAutoDelete设为false,并且在退出进程前,将指向线程类CWinThread的指
11、针pWinThread删除。,16.3.1 线程的创建,二、AfxBeginThread函数用来创建用户界面线程的调用格式:,CWinThread*AfxBeginThread(CRuntimeClass*pThreadClass,int nPriority=THREAD_PRIORITY_NORMAL,UINT nStackSize=0,DWORD dwCreateFlags=0,LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);,16.3.1 线程的创建,pfnThreadProc:指向CRuntimeClass类的指针。其它参数的说明与前面相同。,1
12、.参数说明:,16.创建用户界面线程的过程:,1)从CWinThread类派生一个新类,派生类必须用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏来声明和实现;,16.3.1 线程的创建,2)重载派生类的InitInstance、ExitInstance等函数,在InitInstance函数中添加代码。,四、通过例题演示利用AfxBeginThread函数创建工作者线程和用户界面线程的过程。,16.3.1 线程的创建,三、关于CreateThread()函数的一些说明:见附带文件2。,16.3.2 线程的启动,线程启动时的初始状态可以通过AfxBeginThrea
13、d()函数的dwCreateFlags参数指定。如下:,0:线程在创建后立即执行;CREATE_SUSPENDED:线程在创建后立即挂起;,所谓挂起就是暂停线程的执行。,16.3.3 线程的终止,遇到以下情况时,线程终止执行:,1.线程控制函数返回(即执行了return语句)。,16.线程自身调用函数ExitThread()函数即终止自己。该函数的原型如下:VOID WINAPI ExitThread(DWORD dwExitCode);该函数通过参数dwExitCode给线程设置退出码后,即终止线程的执行。,16.3.3 线程的终止,3.同一进程或其他进程的线程调用TerminateThre
14、ad函数,其原型为:BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);,该函数用来结束由hThread参数指定的线程,并把dwExitCode设成该线程的退出码。当某个线程不再响应时,我们可以用其他线程调用该函数来终止这个不响应的线程。,16.3.3 线程的终止,4.包含线程的进程被终止,如其它进程调用TerminateProcess函数终止进程的执行,或进程自身调用ExitProcess函数终止自身的执行。,BOOL WINAPI TerminateProcess(HANDLE hProcess,UINT uExitCode);,Te
15、rminateProcess函数的原型为:,VOID WINAPI ExitProcess(UINT uExitCode);,ExitProcess函数的原型为:,16.3.3 线程的终止,5.调用全局函数AfxEndThread终止进程;,注意:最好使用第1种方式终止线程,第24种方式都不宜采用。,16.4.1 线程的运行状态的设置,16.4 线程的操作和管理,1.当参数dwCreateFlags置为0时,调用AfxBeginThread函数创建的线程一启动就立即执行。这时,如果想暂停该线程的执行,可调用其成员函数SuspendedThread()函数将自身挂起。,AfxEndThread函
16、数的dwCreateFlags参数是决定线程在创建时的运行状态的。,16.4.1 线程的运行状态的设置,16.当参数dwCreateFlags置为CREATE_SUSPENDED时,调用AfxBeginThread函数创建的线程一启动就挂起,暂停执行。这时,如果想继续执行线程,可调用成员函数ResumeThread()函数唤醒被挂起的线程。,被挂起的线程不能调用此函数唤醒自身,必须由一个未被挂起的处于运行状态的线程调用此函数来取消挂起。,注意:,16.4.2 线程的优先级,一、Windows操作系统是根据进程和线程的优先级来确定它们的排队顺序并分配CPU时间的,所以对于进程和线程在其创建时要设
17、置优先级。,二、线程的优先级是根据其创建时设置的优先级和拥有该线程的进程的优先级来确定的。其最终的优先级是0到31之间的数值,数值越大,优先级越高。其中,015级是普通优先级,16 30级是实时优先级。,16.4.2 线程的优先级,Windows操作系统对具有普通优先级的线程的调度特点是:高优先级线程先运行,只有高优先级线程不运行时,才调度低优先级线程运行。优先级相同的线程按照时间片轮流运行。,三、Windows操作系统对线程的调度特点,16.4.2 线程的优先级,四、Windows操作系统对具有实时优先级的线程的调度特点是:高优先级线程先运行,只有高优先级线程不运行时,才调度低优先级线程运行
18、。优先级相同的线程不按照时间片轮转,而是先运行的线程就先控制CPU,如果它不主动放弃控制,同级或低优先级的线程就无法运行。,16.4.2 线程的优先级,五、用函数AfxBeginThread创建线程时,其参数nPriority指定新线程的优先级,该参数的取值为以下七个值之一:,THREAD_PRIORITY_TIME_CRITICALTHREAD_PRIORITY_HIGHEST THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_NORMALTHREAD_PRIORITY_BELOW_NORMALTHREAD_PRIORITY_LOWESTTHREAD_
19、PRIORITY_IDLE,16.4.2 线程的优先级,对这七个值的说明,及线程最终优先级的确定:见附带文件3。,六、如何改变线程的优先级?,在应用程序中,如果需要改变线程的优先级,可以通过线程类的成员函数SetThreadPriority()对线程的优先级重新设置。其原型如下:BOOL SetThreadPriority(int nPriority)成功执行后返回非零值,不成功返回0。,16.4.2 线程的优先级,七、如何获得线程的优先级?,在应用程序中,有时需要查询线程的优先级,这时可以通过线程类的成员函数GetThreadPriority()获得线程的优先级。其原型如下:int GetT
20、hreadPriority(HANDLE hThread)返回THREAD_PRIORITY_ERROR_RETURN 表示失败。成功时返回优先级的七个值。,16.4.2 线程的优先级,八、Windows动态调度线程的说明,线程的优先级不是一直不变的,Windows操作系统对线程从优先级进行动态调整,以保证所有的线程都能较好的运行。当线程长时间挂起以等待激活它再次运行的信号时,比它优先级低的线程将难以得到所需的CPU时间。这种情况下,当如果某线程在一段时间没有运行,Windows操作系统将提高它的优先级以保证其获得CPU时间。,16.4.3 线程间的通信,一、用简单的布尔型变量实现线程间的通信
21、 见P40例题,二、通过消息的发送和处理来实现线程和主程序之间的通信,1.调用:PostMessage(),其原型为:,16.4.3 线程间的通信,BOOLPostMessage(HWND hWnd,/要发送到的窗口的句柄 UINT Msg,/消息的ID值 WPARAM wParam,/消息的第一个参数 LPARAM lParam/消息的第二个参数);,如果执行成功返回非零值,不成功返回0。,16.4.3 线程间的通信,实现方法:,1)在头文件中定义一个消息,如线程终止的消息:const WM_THREADENDED WM_USER+10,2)加入相应的消息处理函数的声明:afx_msg LO
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+ 课件 16 任务 多线程 编程
链接地址:https://www.31ppt.com/p-6154042.html