C++创建新线程的四种方式:

方式一(不推荐):CreateThread(记得关闭线程句柄) CreateThread是一种微软在Windows API中提供了建立新的线程的函数,该函数在主线程的基础上创建一个新线程。线程终止运行后,线程对象仍然在系统中,必须通过CloseHandle函数来关闭该线程对象。

DWORD WINAPI Fun(LPVOID lpParamter)
{

int sum = 0;
int i = 0;

while (1)
{
i++;
cout << "i=" << i << endl;
}
}
int main()
{
HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
}

HANDLE WINAPI CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, lpParameter, DWORD dwCreationFlags, lpThreadId );

// 线程安全属性,在Windows NT中,NULL使用默认安全性,不可以被子线程继承,否则需要定义一个结构体将它的bInheritHandle成员初始化为TRUE。因此一般使用NULL

SIZE_T dwStackSize, // 线程堆栈大小 设置初始栈的大小,以字节为单位,如果为0,那么默认将使用与调用该函数的线程相同的栈空间大小。任何情况下,Windows根据需要动态延长堆栈的大小

LPTHREAD_START_ROUTINE lpStartAddress, // 线程函数地址 指向线程函数的指针,形式:@函数名,函数名称没有限制, LPVOID lpParameter, // 线程函数参数 是一个指向结构的指针,不需传递参数时,为NULL

DWORD dwCreationFlags, // 指定线程是否立即启动 一般取值为0(立即激活)或者为)CREATE_SUSPENDED(0x00000004)挂起线程 LPDWORD lpThreadId // 存储线程ID号 ); 

返回值:函数成功,返回线程句柄;函数失败返回false。若不想返回线程ID,设置值为NULL。

函数声明方式 DWORD WINAPI 函数名 (LPVOID lpParam); //标准格式

DWORD WINAPI 函数名 (LPVOID lpParam) { return 0; } CreateThread(NULL, 0, 函数名, NULL, 0, NULL); 1 2 3 4 5 void 函数名(); 也就是普通的没有标准的函数声明方式

需要注意:使用void 函数名()此种线程声明方式时,lpStartAddress需要加入LPTHREAD_START_ROUTINE转换,也就是创建线程时第三个参数要写成(LPTHREAD_START_ROUTINE)函数名

创建方式的缺点:使用这种方法可能会引发内存泄漏问题,不推荐,推荐使用方式三

方式二(简单):_beginthread()

unsigned long _beginthread( void(_cdecl *start_address)(void *), //声明为void (*start_address) (void *)形式 unsigned stack_size, //是线程堆栈大小,一般默认为0 void *arglist //向线程传递的参数,一般为结构体 );

_Beginthread函数创建一个在start_address开始执行例程的线程。 当线程从该例程返回时,就会自动终止。使用此函数必须包含头文件 #include <process.h>

这个函数看起来过于简单,他无法做到线程的挂起状态。另外重要的一点是,它所产生出来的线程所做的第一件事情就是关闭掉handle,所以由它所返回的handle可能可用,也可能不可用

方式三(推荐,安全度高):_beginthreadex(需要关闭线程句柄) uintptr_t _beginthreadex( // NATIVE CODE void *security, unsigned stack_size, unsigned ( __stdcall *start_address )( void * ), void *arglist, unsigned initflag, unsigned *thrdaddr ); 1 2 3 4 5 6 7 8 需要使用头文件#include <process.h> 需要的设置:ProjectàSetting–>C/C+±->User run-time library 选择Debug Multithreaded 或者Multithreaded。即使用: MT或MTD。退出时需要使用_endthreadex(handle);

方式四AfxBeginThread(会自动释放的,不用你去释放) AfxBeginThread一个计算机函数,功能是创建用户界面线程和工作者线程。 常见用法是AfxBeginThread(ThreadProc,this)。比较常见的就是在MFC里面使用。两者的区别在于用户页面能够处理消息响应,而后者工作者线程则不能。

主要介绍工作者线程:

CWinThread* AFXAPI AfxBeginThread( AFX_THREADPROC pfnThreadProc,// 线程的入口函数,声明一定要如下: UINT MyThreadFunction( LPVOID pParam );

LPVOID pParam,//传递入线程的参数,注意它的类型为:LPVOID,所以我们可以传递一个结构体入线程.

int nPriority,//优先级

UINT nStackSize,//堆栈大小 DWORD

dwCreateFlags,//创建标识,是否挂起 LPSECURITY_ATTRIBUTES lpSecurityAttrs//安全属性 ) 一个是线程函数的指针,一个是传递给这个函数的参数。

实际中我们经常这样用 AfxBeginThread(ThreadProc,this);//把this传过去,就可以调用类的成员了. 这样线程函数就可以使用和操作类的成员了。千万要注意线程函数是静态类函数成员。当然也可以把this换成别的结构体指针,效果一样。

需要注意的是,声明必须是这种方式

UINT MyThreadProc( LPVOID pParam ) { return 0; }