windows程序设计3.ppt

上传人:qwe****56 文档编号:70105962 上传时间:2023-01-16 格式:PPT 页数:39 大小:276KB
返回 下载 相关 举报
windows程序设计3.ppt_第1页
第1页 / 共39页
windows程序设计3.ppt_第2页
第2页 / 共39页
点击查看更多>>
资源描述

《windows程序设计3.ppt》由会员分享,可在线阅读,更多相关《windows程序设计3.ppt(39页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

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为保持线程同步而申请的为

19、保持线程同步而申请的内存空间,然后再调用内存空间,然后再调用ExitThread函数来终止线程。函数来终止线程。同步可以保证在一个时间内只有一个线程同步可以保证在一个时间内只有一个线程对某个共享资源有控制权。共享资源包括全局对某个共享资源有控制权。共享资源包括全局变量、公共数据成员或者句柄等。临界区对象变量、公共数据成员或者句柄等。临界区对象和事件内核对象可以很好的用于多线程同步和和事件内核对象可以很好的用于多线程同步和它们之间的通信。它们之间的通信。3.2 线程同步线程同步1 临界区对象临界区对象临界区对象是定义在数据段中的一个临界区对象是定义在数据段中的一个CRITICAL_SECTION

20、结构,结构,Windows内部内部使用这个结构记录一些信息,确保在同一时间使用这个结构记录一些信息,确保在同一时间只有一个线程访问该数据段的数据。只有一个线程访问该数据段的数据。编程时,要把临界区对象定义在想保护的编程时,要把临界区对象定义在想保护的数据段中,然后在任何线程使用此临界区对象数据段中,然后在任何线程使用此临界区对象之前对它进行初始化。之前对它进行初始化。void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)/指向数据段中定义的指向数据段中定义的CRITICAL_SECTION结构结构之后,线程访问临

21、界区中数据的时候,必须调用之后,线程访问临界区中数据的时候,必须调用EnterCriticalSection函数,申请进入临界区(关键代码函数,申请进入临界区(关键代码段)。若一个线程在临界区,函数就会一直等下去。段)。若一个线程在临界区,函数就会一直等下去。void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)当操作完成时,还要将临界区还给当操作完成时,还要将临界区还给Windows,以便其他线程可以申请使用。,以便其他线程可以申请使用。void LeaveCriticalSection(LPCRITICAL_SECTI

22、ON lpCriticalSection)当程序不再使用临界区对象的时候,必须使用当程序不再使用临界区对象的时候,必须使用DeleteCriticalSection函数将它删除。函数将它删除。void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection)临界区对象能够很好的保护共享数据,但是它不能够用于进临界区对象能够很好的保护共享数据,但是它不能够用于进程之间资源的锁定,因为它不是内核对象。如果要在进程间维持程之间资源的锁定,因为它不是内核对象。如果要在进程间维持线程的同步可以使用事件内核对象。线程的同步可以使用事件内核对象。

23、2 互锁函数互锁函数 互锁函数为同步访问多线程共享变量提供了一互锁函数为同步访问多线程共享变量提供了一个简单的机制。如果变量在共享内存,不同进程的个简单的机制。如果变量在共享内存,不同进程的线程也可以使用此机制。线程也可以使用此机制。用于互锁的函数有用于互锁的函数有InterlockedIncrement、InterlockedDecrement、InterlockedExchangeAdd、InterlockExchangePointer等。等。如果只是简单的保护一个共享变量,可以使用互如果只是简单的保护一个共享变量,可以使用互锁函数:锁函数:LONGInterlockedIncrement

24、(LONGvolatile*Addend);/递递增指定的增指定的32位变量位变量LONGInterlockedDecrement(LONGvolatile*Addend);/递递减指定的减指定的32位变量位变量这两个函数可以阻止其他线程同时访问此变量。这两个函数可以阻止其他线程同时访问此变量。其他互锁函数其他互锁函数(1)LONGInterlockedExchangeAdd(LPLONGAddend,LONGIncrement);Addend为长整型变量的地址,为长整型变量的地址,Increment为想要在为想要在Addend指向的长整型变量指向的长整型变量上增加的数值(可以是负数)。这个函

25、数的主要作用是保证这个加操作为一上增加的数值(可以是负数)。这个函数的主要作用是保证这个加操作为一个原子访问。个原子访问。(2)LONGInterlockedExchange(LPLONGTarget,LONGValue);用第二个参数的值取代第一个参数指向的值。函数返回值为原始值。用第二个参数的值取代第一个参数指向的值。函数返回值为原始值。(3)PVOIDInterlockedExchangePointer(PVOID*Target,PVOIDValue);用第二个参数的值取代第一个参数指向的值。函数返回值为原始值。用第二个参数的值取代第一个参数指向的值。函数返回值为原始值。(4)LONGI

26、nterlockedCompareExchange(LPLONGDestination,LONGExchange,LONGComperand);如果第三个参数与第一个参数指向的值相同,那么用第二个参数取代第一个如果第三个参数与第一个参数指向的值相同,那么用第二个参数取代第一个参数指向的值。函数返回值为原始值。参数指向的值。函数返回值为原始值。(5)PVOIDInterlockedCompareExchangePointer(PVOID*Destination,PVOIDExchange,PVOIDComperand);如果第三个参数与第一个参数指向的值相同,那么用第二个参数取代第一个如果第三个

27、参数与第一个参数指向的值相同,那么用第二个参数取代第一个参数指向的值。函数返回值为原始值。参数指向的值。函数返回值为原始值。3事件内核对象事件内核对象 多线程程序设计大多会涉及线程间相互通多线程程序设计大多会涉及线程间相互通信。主线程在创建工作线程时,可以通过参数信。主线程在创建工作线程时,可以通过参数给工作线程传递初始化数据,当工作线程开始给工作线程传递初始化数据,当工作线程开始运行后,还需要通过通信机制来控制工作线程。运行后,还需要通过通信机制来控制工作线程。同样,工作线程有时也需要将一些情况主动通同样,工作线程有时也需要将一些情况主动通知主线程。一种比较好的方法就是使用事件内知主线程。一

28、种比较好的方法就是使用事件内核对象。核对象。事件内核对象事件内核对象事件内核对象是一种抽象的对象,它也有未受信和受事件内核对象是一种抽象的对象,它也有未受信和受信两种状态,可以使用信两种状态,可以使用WaitForSingleObject函数等待函数等待其变成受信状态。不同于其他内核对象的是一些函数其变成受信状态。不同于其他内核对象的是一些函数可以使事件对象在这两种状态之间转化。可以把事件可以使事件对象在这两种状态之间转化。可以把事件对象看成是一个设置在对象看成是一个设置在Windows内部的一个标志。他内部的一个标志。他的状态设置和测试工作由的状态设置和测试工作由Windows来完成。来完成

29、。事件对象包含事件对象包含3个成员:个成员:nUsageCount:使用计数:使用计数bManualReset:是否人工重置:是否人工重置bSignaled:是否受信:是否受信基本函数基本函数使用使用CreateEvent函数创建事件对象:函数创建事件对象:HANDLECreateEvent(LPSECURITY_ATTTIBUTESlpEventAttributes,/用来定义事件对象的安全属性用来定义事件对象的安全属性BOOLbManualReset,/指定是否需要手工重置事件对象为为受信状态指定是否需要手工重置事件对象为为受信状态BOOLbInitialState,/指定事件对象创建时的

30、初始状态指定事件对象创建时的初始状态LPCWSTRlpName);/事件对象的名称事件对象的名称根据根据lpName对象的名字查询,返回事件对象句柄:对象的名字查询,返回事件对象句柄:HANDLEOpenEvent(DWORDdwDesiredAccess,/指定想要的访问权限指定想要的访问权限BOOLbInheritHandle,/指定返回句柄是否被继承指定返回句柄是否被继承LPCWSTRlpName);/要打开的事件对象的名称要打开的事件对象的名称BOOLSetEvent(HANDLEhEvent);/将事件状态设为将事件状态设为“受信受信(sigaled)”BOOLResetEvent(

31、HANDLEhEvent);/将事件状态设为将事件状态设为“未受信未受信(nonsigaled)”4信号量内核对象信号量内核对象信号量内核对象允许多个线程在同一时刻访问统一资信号量内核对象允许多个线程在同一时刻访问统一资源,但需要限制在同一时刻访问此资源的最大线程数源,但需要限制在同一时刻访问此资源的最大线程数据。据。-创建信号量对象创建信号量对象HANDLECreateSemaphore(LPSECURITY_ATTRIBUTESlpSemaphoreAttributes,/安全属性指针安全属性指针LONGlInitialCount,/初始计数初始计数LONGlMaximumCount,/最

32、大计数最大计数LPCTSTRlpName/对象名指针对象名指针););打开信号量内核对象打开信号量内核对象HANDLEOpenSemaphore(DWORDdwDesireAccess,/访问标志访问标志BOOLbInheritHandle,/继承标志继承标志LPCTSTRlpName/对象名指针对象名指针););内核对象,可以在其他进程中通过名字得到并打开内核对象,可以在其他进程中通过名字得到并打开释放信号量内核对象释放信号量内核对象BOOLReleaseSemaphore(HANDLEhSemaphore,/信号量句柄信号量句柄LONGlReleaseCount,/级数递增数量级数递增数量

33、LPLONGlpPreviousCount/先前计数先前计数););5互斥内核对象互斥内核对象互斥内核对象,可以保证多个线程对同一共享资源的互斥内核对象,可以保证多个线程对同一共享资源的互斥访问,与临界区类似。只有拥有互斥对象的线程互斥访问,与临界区类似。只有拥有互斥对象的线程才具有访问资源的权限。由于互斥对象只有一个,因才具有访问资源的权限。由于互斥对象只有一个,因此决定了在任何情况下此共享资源都不会同时被多个此决定了在任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以

34、将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。访问资源。与其他内核对象不同,互斥对象在操作系统中拥有特与其他内核对象不同,互斥对象在操作系统中拥有特殊代码,并由操作系统来管理,操作系统甚至还允许殊代码,并由操作系统来管理,操作系统甚至还允许其进行一些其他内核对象所不能进行的非常规操作。其进行一些其他内核对象所不能进行的非常规操作。创建或打开互斥内核对象创建或打开互斥内核对象HANDLECreateMutex(LPSECURITY_ATTRIBUTESlpSemaphoreAttributes,/安全属性指针安全属性指针BOOLbInitialOwner,/初始拥有者初始拥有者LPCT

35、STRlpName/互斥对象名互斥对象名););打开互斥内核对象打开互斥内核对象HANDLEOpenMutex(DWORDdwDesiredAccess,/访问标志访问标志BOOLbInheritHandle,/继承标志继承标志LPCTSTRlpName/互斥对象名互斥对象名););释放互斥内核对象释放互斥内核对象BOOLReleaseMutex(HANDLEhMutex););其他内核对象在没有得到通知时,受调用等待函数的其他内核对象在没有得到通知时,受调用等待函数的作用,线程将会挂起,同时失去可调度性,而互斥内作用,线程将会挂起,同时失去可调度性,而互斥内核对象可以在等待的同时仍具有可调度

36、性,这样也就核对象可以在等待的同时仍具有可调度性,这样也就能完成非常规操作。能完成非常规操作。编程时,互斥对象多用在对那些为多个线程所访问的编程时,互斥对象多用在对那些为多个线程所访问的内存块的保护上,可以确保任何线程在处理此内存块内存块的保护上,可以确保任何线程在处理此内存块时都拥有可靠的独占访问权。时都拥有可靠的独占访问权。线程局部存储线程局部存储“有必要存在一些唯一于各个线程的持久性存储有必要存在一些唯一于各个线程的持久性存储”。同一个进程中的多个线程,它们的内存空间同一个进程中的多个线程,它们的内存空间是共享的(栈除外),在一个线程修改的内存内是共享的(栈除外),在一个线程修改的内存内

37、容,对所有线程都生效。这是一个优点也是一个容,对所有线程都生效。这是一个优点也是一个缺点。说它是优点,线程的数据交换变得非常快缺点。说它是优点,线程的数据交换变得非常快捷。说它是缺点,一个线程死掉了,其它线程也捷。说它是缺点,一个线程死掉了,其它线程也性命不保性命不保;多个线程访问共享数据,需要昂贵的同多个线程访问共享数据,需要昂贵的同步开销,也容易造成同步相关的步开销,也容易造成同步相关的BUG。线程局部存储线程局部存储DWORDTlsAlloc(VOID);/获得索引获得索引BOOLTlsFree(/释放索引释放索引DWORDdwTlsIndex/TLS索引索引);BOOLTlsSetValue(/将一个指针和某个线程及某个线程索引相关联将一个指针和某个线程及某个线程索引相关联DWORDdwTlsIndex,/TLS索引索引LPVOIDlpTlsValue/要存储的值要存储的值);LPVOIDTlsGetValue(/得到需要使用的指针得到需要使用的指针DWORDdwTlsIndex/TLS索引索引);搜索文件的基础知识搜索文件的基础知识编程思路编程思路3.3 多线程文件搜索器多线程文件搜索器结结 束束

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 其他杂项

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁