Win32提供了一系列的API函数来完成线程的创建、挂起、恢复、终止以及通信等工作,见表5-1。
表5-1 Win32中常用的多线程API函数
下面将对表5-1其中的函数进行详细的描述。
(1)HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄。其中各参数说明如下:
lpThreadAttributes:指向一个SECURITY_ATTRIBUTES结构的指针,该结构决定了被创建的线程句柄由当前活动进程的子进程所继承。如果lpThreadAttributes被置为NULL,则表示不能被其子进程所继承。
dwStackSize:指定线程的堆栈大小。如果为0,那么线程的堆栈大小与进程相同。
lpStartAddress:指向在应用程序中定义的类型为LPTHREAD_START_ROUTINE的函数的指针,lpStartAddress表示新线程开始执行时代码所在函数的地址。
lpParameter:传递给线程的一个32位的参数。
dwCreationFlags:控制线程创建的附加标志,可以取两种值。如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,初始化CPU,登记CONTEXT结构的成员,使该线程处于就绪状态,并不马上执行,而是挂起该线程,直至函数 ResumeThread被调用。
lpThreadId:该参数指定了所创建线程的ID。对于Win95/98,该参数是必需的,不能为NULL。
(2)DWORD SuspendThread (HANDLE hThread)
该函数用于挂起指定的线程,如果函数执行成功,则线程的执行被终止(指用户为其指定代码)。
每个线程都有一个挂起状态计数值,其最大值为一个常数MAXIMUM_SUSPEND_COUNT。当该计数值大于零时,线程处于挂起状态。当该计数值为零时,线程处于正常执行的状态,并且可能被调度程序装入CPU中运行。调用SuspendThread (hThread)导致由hThread标识的线程的挂起状态计数值加1。当其已经达到了最大值,再试图挂起该线程将导致调用错误。参数hThread表示将被挂起线程的句柄。
如果该函数执行成功,则函数返回调用前的线程挂起状态计数值,否则返回值被置为0xFFFFFFFF。另外,在创建线程时,使用CREATE_SUSPENDED标志也可以挂起线程。
(3)DWORD ResumeThread (HANDLE hThread)
将由hThread标识的线程的挂起状态计数值减1。
如果该函数执行成功,则返回由hThread句柄所标识的线程在调用前所拥有的挂起状态计数值。如果失败,则返回0xFFFFFFFF。
(4)VOID ExitThread ( DWORD dwExitCode )
该函数用于线程终止自身的执行,主要在线程的执行函数中被调用。它将线程退出码设置为dwExitCode后,终止该线程的执行。值得注意的是,调用ExitThread后,并不能确保从系统中清除指定的线程对象。只有当该线程对象的最后一个句柄被关闭后,线程对象才被彻底清除。
(5)BOOL TerminateThread (HANDLE hThread, DWORD dwExitCode)
一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用TerminateThread强行终止某一线程的运行。各参数含义如下:
hThread:将被终结的线程的句柄。
dwExitCode:用于指定线程的退出码。(www.xing528.com)
如果函数执行成功,则返回非0值,否则返回0值。
使用TerminateThread()终止某个线程的执行是不安全的,可能会引起系统不稳定;虽然该函数立即终止线程的执行,但并不释放线程所占用的资源,例如为线程初始分配的堆栈等。另外,与ExitThread()函数类似,调用该函数也不能保证将hThread所指定的线程对象从系统中清除。只有当该线程对象的最后一个句柄被关闭后,该线程才会被彻底删除。
(6)BOOL PostThreadMessage (DWORD IdThread, UINT Msg ,
PARAM wParam, LPARAM lParam )
该函数将一条消息放入到指定线程的消息队列中,并且不等到消息被该线程处理时便返回。
IdThread:将接收消息的线程的ID;
Msg:指定用来发送的消息;
wParam:同消息有关的字参数;
lParam:同消息有关的长参数;
调用该函数时,如果即将接收消息的线程没有创建消息循环,则该函数执行失败。如果该线程没有消息循环,可以调用PeekMessage (&msg,NULL, WM_USER, WM_USER,PM_NOREMOVE)来创建消息队列,但要注意的是,要保证系统在创建了消息队列之后才调用PostThreadMessage函数,这一点要用后面将涉及到的线程同步来实现。
接收消息的线程可以调用函数GetMessage()和PeekMessage()从线程的消息队列中获取消息,并且在该线程所接收到的消息中,hWnd被设置为NULL。
(7)BOOL SetThreadPriority (HANDLE hThread, int nPriority)
该函数用来设定指定线程在其所在的进程中的相对优先级。各参数含义如下:
hThread:指向待设定相对线程优先级的线程的句柄。
nPriority:指定线程优先级的常数,优先级由低到高,可以取以下值:
THREAD_PRIORITY_IDLE
THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_HIGHEST
THREAD_PRIORITY_CRITICAL
关于各常数的意义请参看Visual C++的联机帮助。
如果该函数对线程的相对优先级设定成功,则返回非零值;否则返回零值。
一般而言,在Windows 95和Windows NT操作系统当中,任务是有优先级的,共有32级,分别对应0到31;一个线程的基本优先级首先属于一个进程的优先级类,然后是其在该优先级类中的相对位置(即上述函数所设定的值)。线程的基本优先级可以表示为进程类基本优先级与线程相对优先级之和;系统按照线程不同的优先级调度线程的运行。0~15级是普通优先级,线程的优先级可以动态变化。高优先级线程优先运行,只有高优先级线程不运行时,才可能调度低优先级线程运行。优先级相同的线程按照时间片轮流占用CPU时间;而16~30级是实时优先级,它与普通优先级的最大区别在于相同优先级进程的运行不按照时间片轮转,而是先运行的线程就先控制CPU,如果它不主动放弃对CPU的控制,同级或低优先级的线程就无法运行。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。