使用_beginthreadex()函数,需使用头文件<processs.h>,且进行编译环境的设置(详见上篇文章)。
线程的创建和终止
C++代码:
#include<iostream>
#include<windows.h>
#include<process.h>
using namespace std;
static unsigned _stdcall Thread1(void *param);
static unsigned _stdcall Thread2(void *param);
int main()
{
//创建第一个线程
HANDLE T1;
unsigned T1_ID;
T1= (HANDLE)_beginthreadex( NULL,
0,
Thread1,
NULL,
CREATE_SUSPENDED,
&T1_ID );
if ( T1 == 0 ) cout<<"Failed to create Thread1..."<<endl;
DWORD T1Code;
GetExitCodeThread(T1, &T1Code ); // should be STILL_ACTIVE = 0x00000103 = 259
cout<<"Initial Thread1 Exit Code is "<<T1Code<<endl;
//创建第二个线程
HANDLE T2;
unsigned T2_ID;
T2=(HANDLE)_beginthreadex(
NULL,
0,
Thread2,
NULL,
CREATE_SUSPENDED,
&T2_ID);
if(T2==0) cout<<"Failed to create Thread2..."<<endl;
DWORD T2CODE;
GetExitCodeThread(T2,&T2CODE);
cout<<"Initial Thread2 Exit Code is "<<T2CODE<<endl;
ResumeThread( T1 );
ResumeThread( T2 );
WaitForSingleObject( T1, INFINITE );
WaitForSingleObject( T2, INFINITE );
CloseHandle( T1 );
CloseHandle( T2 );
return 0;
}
static unsigned _stdcall Thread1(void *param)
{
cout<<"The Thread1 IS WORKING..."<<endl;
Sleep(500);
return 1;
}
static unsigned _stdcall Thread2(void *param)
{
Sleep(500);
cout<<"The Thread2 IS WORKING..."<<endl;
return 1;
}
代码详解
与CreateThread()相同的部分不再赘述
- _beginthreadex()函数,比_beginthread()更安全一些.因为beginthread隐式调用了CloseHandle关闭了线程句柄,而与_beginthreadex成对使用的_endthreadex则没有关闭线程的句柄,需要显示调用CloseHandle来关闭线程句柄,从逻辑上更安全。
_beginthreadex()函数原型:
_beginthreadex(
void *secAttr,
unsigned stackSize,
unsigned (__stdcall *threadFunc)(void *),
void *param,
unsigned flags,
unsigned *threadID);
_beginthreadex()的参数类似于CreateThread()的参数,且与CreateThread()指定的参数有相同的含义。
函数说明:
1. 第一个参数secAttr是描述线程内核对象安全属性的指针,设置为NULL,就会使用默认的安全描述符。
2. 第二个参数stackSize表示线程栈空间大小。如果为0(1MB),那么这个线程堆栈的大小与创建它的线程相同。
3. threadFunc表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址,线程的执行一直持续到线程函数返回。 这个函数的地址在下面的函数中指定。每个线程函数都必须具有这样的原型。线程函数的地址(也就是线程的入口点)在Thread中指定。对于_beginthreadex(),线程函数的原型如下:
static unsigned_stdcall Thread(void *param)
这个原型在功能上等价于CreateThread()的线程函数的原型,但是它使用了不同的类型名称。
stdcall的调用约定意味着:
1)参数从右向左压入堆栈;
2)函数自身修改堆栈;
3)函数名自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸。。
4.第四个参数param是传给线程函数的参数。
5.第五个参数flags标志了线程的执行状态,为0表示线程创建之后立即就可以进行调度,如果为CREATE_SUSPENDED,线程则以挂起状态创建并等待执行,这样它就无法调度,直到调用ResumeThread()。
6.第六个参数threadid将以的长整型返回线程的ID号,传入NULL表示不需要返回该线程ID号。
- ResumeThread( ); 线程恢复函数。
函数原型:DWORD WINAPI ResumeThread( __in HANDLE hThread);
HANDLE hThread你需要恢复线程的句柄使用该函数能够激活线程的运行,使CPU分配资源让线程恢复运行。 - GetExitCodeThread();用于获取一个已中止线程的退出代码。
BOOL GetExitCodeThread (
HANDLE hThread,
LPDWORD lpExitCode
);
hThread Long,想获取退出代码的一个线程的句柄
lpExitCode Long,用于装载线程退出代码的一个长整数变量。如线程尚未中断,则设为常数STILL_ACTIVE。