在使用涉及到CRT存储堆操作的CRT库函数中的多线程编程中,使用CreateThread来开始线程是很危险的,容易造成线程的意外终止,windows核心编程中推荐使用_beginthread、_beginthreadx和相对应的_endthread、_endthreadx函数
uintptr_t _beginthread( // NATIVE CODE
void( __cdecl *start_address )( void * ),
unsigned stack_size,
void *arglist
);
- start_address-开启线程中要使用的函数名,__cdecl的调用约定就是C++默认的调用的约定,所以定义函数时定义成普通的常用函数就行,只是函数的返回值为void,传入参数为void*
- stack_size-定义栈的大小
- arglist-参数列表,也可传入多个参数
- 返回值需要用HANDLE强制转换
uintptr_t _beginthreadex( // NATIVE CODE
void *security,
unsigned stack_size,
unsigned ( __stdcall *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
此函数的使用方式和CreateThread相同,函数参数的类型相同,只是返回值需要强制转换成HANDLE
void _endthread( void ); void _endthreadex(unsigned retval);
_endthread,用于函数内部终止自己的线程执行,可以自动回收线程资源,自动关闭句柄
_endthreadx,可传入自定义的退出码,不能自动回收线程资源,不能关闭句柄(和ExitThread的作用,性能类似)
上述说明只是创建新线程和终止线程是使用这种类型的,其他的操作方法(挂起,恢复挂起,等待)都还是一样的
一下四种情况中要使用上述的函数,不要使用createThread类的函数
- 使用malloc和free,或是new和delete
- 使用stdio.h或io.h里面声明的任何函数(如printf)
- 使用浮点变量或浮点运算函数
- 调用任何一个使用了静态缓冲区的runtime函数,如asctime(),strtok(),rand()等
例程,线程函数传入多个参数:
// 使用运行时库开启多线程.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <process.h>
#include <Windows.h>
#include <iostream>
using namespace std;
void threadfun(void* param)
{
int *pp = (int*)param;
for (int i = 1; i <= 6; ++i)
{
cout << pp[0]<<' '<<pp[1]<<' '<<pp[2] << endl;
Sleep(1000);
}
cout << "子线程运行结束" << endl;
}
int main()
{
cout << "主线程开始运行" << endl;
int p[] = { 1,2,3 };
HANDLE hThread = (HANDLE)_beginthread(threadfun, 0, p);
WaitForSingleObject(hThread, INFINITE);
cout << "主线程运行结束" << endl;
return 0;
}