windows程序设计3.ppt





《windows程序设计3.ppt》由会员分享,可在线阅读,更多相关《windows程序设计3.ppt(39页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、Windows程序设计基础程序设计基础进程进程主线程主线程辅助线程辅助线程第三章第三章windows程序的执行单元程序的执行单元3.1多线程多线程 主线程在运行过程中还可以创建新的主线程在运行过程中还可以创建新的线程,即多线程。在同一进程中运行不同线程,即多线程。在同一进程中运行不同的线程的好处是这些线程可以共享进程的的线程的好处是这些线程可以共享进程的资源,如全局变量、句柄等。各个线程也资源,如全局变量、句柄等。各个线程也可以有自己的私有堆栈用于保存私有数据。可以有自己的私有堆栈用于保存私有数据。线程的创建线程的创建 线程描述了进程内代码的执行路径。进程线程描述了进程内代码的执行路径。进程内
2、可以有多个线程在执行,为了使他们内可以有多个线程在执行,为了使他们“同时同时”运行,操作系统为每个线程轮流分配运行,操作系统为每个线程轮流分配CPU时时间片。间片。一般情况下,应用程序使用主线程接受用一般情况下,应用程序使用主线程接受用户的输入,显示运行结果,而创建新的线程来户的输入,显示运行结果,而创建新的线程来处理长时间的操作。处理长时间的操作。每个线程必须有一个进入点函数,线程从每个线程必须有一个进入点函数,线程从这个进入点开始运行。这个进入点开始运行。线程函数线程函数DWORD WINAPI ThreadProc(LPVOID lpParam)WINAPI 是一个宏名,在是一个宏名,在
3、windef.h文件中声明如下:文件中声明如下:#define WINAPI _stdcall_stdcall是新标准是新标准c/c+函数的调用方法。调用方法参数的进栈函数的调用方法。调用方法参数的进栈顺序和顺序和_cdecl一样,都是从右到左。区别:一样,都是从右到左。区别:_stdcall:自动清栈:自动清栈_cdecl:手动清栈手动清栈Windows规定,凡是由它负责调用的函数都必须定义为规定,凡是由它负责调用的函数都必须定义为_stdcall类型。类型。ThreadProc是一个回调函数,即由是一个回调函数,即由Windows负责调用的函数。负责调用的函数。创建新线程函数创建新线程函数
4、HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttribute,/线程安全性线程安全性DWORD dwStackSizem,/指定线程堆栈大小指定线程堆栈大小LPTHREAD_START_ROUTINE lpStartAddress,/线程函数起始地址线程函数起始地址LPVOID lpParameter,/传递给线程函数的参数传递给线程函数的参数DWORD dwCreationFlags,/指定线程创建后是否立即启动指定线程创建后是否立即启动DWORD*lpThreadId/用于取得内核给新线程分配的用于取得内核给新线程分配的ID号号);
5、函数执行成功,返回新建线程的线程句柄,函数执行成功,返回新建线程的线程句柄,lpStartAddress参数指参数指定线程函数的地址,新建线程将从此地址开始执行。直到定线程函数的地址,新建线程将从此地址开始执行。直到return语句返回,语句返回,线程结束,把控制权交给操作系统。线程结束,把控制权交给操作系统。需要注意的两个参数:需要注意的两个参数:lpThreadAttributes:一个指向:一个指向SECURITY_ATTRIBUTES结构的指针,如果需要结构的指针,如果需要默认安全属性,传递默认安全属性,传递NULL,如果希望此线程对象句如果希望此线程对象句柄可以被子进程继承的话,必须
6、设定一个柄可以被子进程继承的话,必须设定一个SECURITY_ATTRIBUTES结构。将它的结构。将它的bInheritHandle成员初始化为成员初始化为TRUE。如下。如下SECURITY_ATTRIBUTESsa;sa.nLength=sizeof(sa);sa.lpSecurityDescriptor=NULL;sa.bInheritHandle=TRUE;/使使CreateThread返回的句柄可以被继承返回的句柄可以被继承HANDLEh=:CreateThread(&sa,);/句柄句柄h可以被子进程继承可以被子进程继承需要注意的两个参数:需要注意的两个参数:dwCreation
7、Flags:创建标志。如果是:创建标志。如果是0,表示线程,表示线程被创建后立即开始运行,如果指定为被创建后立即开始运行,如果指定为CREATE_SUSPENDED标志,表示线程被创建以后标志,表示线程被创建以后处于挂起状态,直到使用处于挂起状态,直到使用ResumeThread函数显式启函数显式启动线程为止。动线程为止。WaitForSingleObject(hHandle,dwMilliseconds)函数函数hHandle:要等待对象的句柄:要等待对象的句柄dwMilliseconds:要等待的时间:要等待的时间该函数用于等待指定的对象变成受信状态。该函数用于等待指定的对象变成受信状态。
8、函数返回条件:函数返回条件:1)等待的对象变成受信状态。)等待的对象变成受信状态。2)参数)参数dwMilliseconds指定的时间已过去。指定的时间已过去。线程内核对象线程内核对象 线程内核对象就是一个包含了线程状态线程内核对象就是一个包含了线程状态信息的数据结构。每次对信息的数据结构。每次对CreateThread函函数的成功调用,系统都会在内部为新的线程数的成功调用,系统都会在内部为新的线程分配一个内核对象。系统提供的管理线程的分配一个内核对象。系统提供的管理线程的函数就是依靠访问线程内核对象来实现管理函数就是依靠访问线程内核对象来实现管理的。的。线程内核对象结构线程内核对象结构CON
9、TEXT(上下文,寄存器状态)(上下文,寄存器状态)UsageCount使用计数(使用计数(2)SuspendCount暂停次数(暂停次数(1)ExitCode退出代码退出代码(STILL_ACTIVE)Signaled是否受信(是否受信(FALSE)EAXEBX其他其他CPU寄存器寄存器创建线程内核对象时,系统对它的各个成员创建线程内核对象时,系统对它的各个成员进行初始化。进行初始化。线程上下文线程上下文CONTEXT每个线程都有自己的一组每个线程都有自己的一组CPU寄存器,称为线程的上下文。这寄存器,称为线程的上下文。这组寄存器的值保存在一个组寄存器的值保存在一个CONTEXT结构里,反映
10、了该线程上结构里,反映了该线程上次运行时次运行时CPU寄存器的状态。寄存器的状态。使用计数使用计数Usage Count该成员记录线程内核对象的使用次数。使用计数初始状态为该成员记录线程内核对象的使用次数。使用计数初始状态为2,创建一个新线程时,因为,创建一个新线程时,因为CreateThread函数返回了线程内函数返回了线程内核对象的句柄,相当于打开一次,就促使核对象的句柄,相当于打开一次,就促使Usage Count值加值加1。如果调用如果调用OpenThread函数,会再加函数,会再加1。因此在使用完它们的句柄之后,一定要调用因此在使用完它们的句柄之后,一定要调用CloseHandle函
11、函数进行关闭。使数进行关闭。使Usage Count值减值减1。如果在刚创建线程时调用如果在刚创建线程时调用CloseHandle函数关闭函数关闭CreateThread函数返回的句柄,函数返回的句柄,Usage Count值减为值减为1,但,但线程没有被终止。线程结束要关闭句柄,不然内存泄露。线程没有被终止。线程结束要关闭句柄,不然内存泄露。暂停次数暂停次数Suspend Count该成员用于指明线程的暂停计数。该成员用于指明线程的暂停计数。DWORD ResumeThread(HANDLE hThread);/唤醒挂起线程唤醒挂起线程DWORD SuspendThread(HANDLE h
12、Thread);/挂起线程挂起线程上面两个函数用于减少或增加上面两个函数用于减少或增加Suspend Count。在相同优先级下,当在相同优先级下,当Suspend Count变为变为0时,系统可以调度该线程时,系统可以调度该线程.退出代码退出代码Exit CodeExit Code指定线程的退出代码,也可以说是线程函数的返回值。在指定线程的退出代码,也可以说是线程函数的返回值。在线程运行期间,线程函数没有返回,值为线程运行期间,线程函数没有返回,值为STILL_ACTIVE。当线程结。当线程结束后,系统自动将束后,系统自动将ExitCode设为线程函数的返回值。可以用设为线程函数的返回值。可
13、以用GetExitCodeThread函数得到线程的退出代码。函数得到线程的退出代码。是否受信是否受信 SignaledSignaled指示了线程对象是否为受信状态。运行期间指示了线程对象是否为受信状态。运行期间FALSE,即未受信,线程结束后,系统把其置为,即未受信,线程结束后,系统把其置为TRUE,针对此对象,针对此对象的等待函数(如的等待函数(如WaitForSingleObject)就会返回。)就会返回。线程的终止线程的终止线程正常终止时,会发生以下事件:线程正常终止时,会发生以下事件:在线程函数中创建的所有在线程函数中创建的所有C+对象将通过它对象将通过它们各自的析构函数被正确的销毁
14、。们各自的析构函数被正确的销毁。该线程使用的堆栈被释放。该线程使用的堆栈被释放。系统将线程内核对象中系统将线程内核对象中ExitCode的值由的值由STILL_ACTIVE设置为线程函数返回的值。设置为线程函数返回的值。系统将递减线程内核对象中系统将递减线程内核对象中Usage Code的的值。值。线程的终止有四种方法线程的终止有四种方法1.线程函数自然退出。线程函数自然退出。2.使用使用ExitThread函数来终止线程。函数来终止线程。3.使用使用TerminateThread函数在一个线程中函数在一个线程中强制终止另一个线程的执行。强制终止另一个线程的执行。4.使用使用ExitProce
15、ss函数结束进程。函数结束进程。线程的优先级线程的优先级线程的优先级范围从线程的优先级范围从0(最低)到(最低)到31(最高)。当你产(最高)。当你产生线程时,并不是直接以数值指定其优先级,而是采用生线程时,并不是直接以数值指定其优先级,而是采用两个步骤。第一个步骤是指定两个步骤。第一个步骤是指定“优先级等级(优先级等级(PriorityClass)”给进程,第二步骤是指定给进程,第二步骤是指定“相对优先级相对优先级”给给该进程所拥有的线程。其中的代码在该进程所拥有的线程。其中的代码在CreateProcess的的dwCreationFlags参数中指定。如果你不指定,系统默参数中指定。如果你
16、不指定,系统默认给的是认给的是NORMAL_PRIORITY_CLASS,除非父进程,除非父进程是是IDLE_PRIORITY_CLASS(那么子进程也会是(那么子进程也会是IDLE_PRIORITY_CLASS)。)。要改变线程优先级,用如下函数:要改变线程优先级,用如下函数:BOOL SetThreadPriority(HANDLE hThread,int nPriority)线程的优先级值线程的优先级值SetThreadPriority的的参参数:数:THREAD_PRIORITY_IDLE空闲空闲THREAD_PRIORITY_LOWEST最低最低THREAD_PRIORITY_BEL
17、OW_NORMAL低于正常低于正常(98)THREAD_PRIORITY_NORMAL正常正常THREAD_PRIORITY_ABOVE_NORMAL高于正常高于正常(98)THREAD_PRIORITY_HIGHEST最高最高THREAD_PRIORITY_TIME_CRITICAL实时实时C/C+运行期库运行期库在实际的开发过程中,一般不直接使用系统提供的在实际的开发过程中,一般不直接使用系统提供的CreateThread函数创建线程,而是使用函数创建线程,而是使用c/c+运行期函运行期函数数_beginthreadex。unsignedlong_beginthreadex(void*se
18、curity,unsignedstack_size,unsigned(_stdcall*start_address)(void*),void*arglist,unsignedinitflag,unsigned*thrdaddr);C/C+运行期库运行期库事实上,这个函数是为了多线程同步的需要。事实上,这个函数是为了多线程同步的需要。相应地,系统使用相应地,系统使用c/c+运行期函数运行期函数_endthreadex代替代替ExitThread函数。函数。void_endthreadex(unsignedretval);这个函数释放这个函数释放_beginthreadex为保持线程同步而申请的为
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- windows 程序设计

限制150内