启动createthread函数(createthread beginthread)
(C++多线程问题)CreateThread()函数问题
当使用CreateProcess调用时,系统将创建一个进程和一个主线程。CreateThread将在主线程的基础上创建一个新线程,大致做如下步骤:
1在内核对象中分配一个线程标识/句柄,可供管理,由CreateThread返回
2把线程退出码置为STILL_ACTIVE,把线程挂起计数置1
3分配context结构
4分配两页的物理存储以准备栈,保护页设置为PAGE_READWRITE,第2页设为PAGE_GUARD
5lpStartAddr和lpvThread值被放在栈顶,使它们成为传送给StartOfThread的参数
6把context结构的栈指针指向栈顶(第5步)指令指针指向startOfThread函数
MSDN中CreateThread原型:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全属性
DWORD dwStackSize, // 堆栈大小
LPTHREAD_START_ROUTINE lpStartAddress, // 线程函数
LPVOID lpParameter, //线程参数
DWORD dwCreationFlags, // 线程创建属性
LPDWORD lpThreadId // 线程ID
);
createthread和beginthread的区别
CreateThread、_beginthread和_beginthreadex都是用来启动
线程的,但大家看到oldworm没有提供_beginthread的方式,考试,大提示beginthread是_beginthreadex的功能子
集,虽然_beginthread内部是调用_beginthreadex但他屏蔽了象安全特性这样的功能,所以_beginthread与
CreateThread不是同等级别,_beginthreadex和CreateThread在功能上完全可替代,我们就来比较一下
_beginthreadex与CreateThread!
CRT的函数库在线程出现之前就已经存在,所以原有的CRT不能真正支持线程,这
导致我们在编程的时候有了CRT库的选择,在MSDN中查阅CRT的函数时都有:
Libraries
LIBC.LIB
Single thread static library, retail version
LIBCMT.LIB
Multithread static library, retail version
MSVCRT.LIB Imp
ort
library for MSVCRT.DLL, retail version
这样的提示!
对于线程的支持是后来
的事!
这也导致了许多CRT的函数在多线程的情况下必须有特殊的支持,不能简单的使用CreateThread就OK。
大多的
CRT函数都可以在CreateThread线程中使用,看资料说只有signal()函数不可以,会导致进程终止!但可以用并不是说没有问题!
有些CRT的函数象malloc(), fopen(), _open(), strtok(), ctime(),
或localtime()等函数需要专门的线程局部存储的数据块,这个数据块通常需要在创建线程的时候就建立,如果使用CreateThread,这个
数据块就没有建立,然后会怎样呢?在这样的线程中还是可以使用这些函数而且没有出错,实际上函数发现这个数据块的指针为空时,会自己建立一个,然后将其与
线程联系在一起,这意味着如果你用CreateThread来创建线程,然后使用这样的函数,会有一块内存在不知不觉中创建,遗憾的是,这些函数并不将其
删除,而CreateThread和ExitThread也无法知道这件事,于是就会有Memory
Leak,在线程频繁启动的软件中(比如某些服务器软件),迟早会让系统的内存资源耗尽!
_beginthreadex(内部也调用
CreateThread)和_endthreadex就对这个内存块做了处理,所以没有问题!(不会有人故意用CreateThread创建然后用
_endthreadex终止吧,而且线程的终止最好不要显式的调用终止函数,自然退出最好!)
谈到Handle的问
题,_beginthread的对应函数_endthread自动的调用了CloseHandle,而_beginthreadex的对应函数
_endthreadex则没有,所以CloseHandle无论如何都是要调用的不过_endthread可以帮你执行自己不必写,其他两种就需要自己
写!(Jeffrey Richter强烈推荐尽量不用显式的终止函数,用自然退出的方式,自然退出当然就一定要自己写CloseHandle)。
CreateThread()函数每个参数都是什么意思,线程问题帮我都解释一下好么!
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParam,
DWORD fdwCreate,
LPDWORD lpIDThread
);
lpsa:线程句柄的安全属性,比如子进程是否可以继承这个线程句柄,一般情况设置为NULL
cbStack:线程栈大小,一般取0表示默认大小
lpStartAddr:线程入口函数 typedef DWORD (__stdcall *LPTHREAD_START_ROUTINE) (
void* lpThreadParameter );在win32程序中默认的调用函数约定就是WINAPI ,__stdcall = WINAPI 。因此你可以声明你的入口函数为:
DWORD WINAPI ThreadProc( void* lpParamete) {//线程中你要做的事情}
lpvThreadParam:就是线程入口函数的参数,就是ThreadProc( void* lpParamete) 的参数
fdwCreate:控制线程创建的标志一般为0,表示线程立即启动。如果你想创建之后把线程挂起来可以传入CREATE_SUSPENDED ,传入这个参数你需要再适当的地方调用ResumeThread 启动线程
lpIDThread:是线程ID返回值,这个用来接收线程返回的ID
写了这么多我还是怕你不懂:
我举个例子吧,我不保证能运行成功,我也没去编译
DWORD WINAPI ThreadProc( void* lpParameter)
{
int *x = (int*)lpParameter;//获得参数的地址
MessageBox(NULL,TEXT("adf"),NULL,MB_OK);
}
DWORD dwThreadID;
int x = 0;
HANDLE hThread = CreateThread(0,0,ThreadProc,(void*)x,0,dwThreadID);
CloseHandle(hThread);
想学习好windows编程MSDN是必须了解的,你居然不知道什么是MSDN,MSDN就是帮助文档,你可以到百度搜一下并把它下载过来,这对你MFC、Windows API、C/C++等很有帮助的
C++多线程函数CreateThread如何使用?
HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, // 指向SECURITY_ATTRIBUTES 的指针,为新线程指定安全描述
__in SIZE_T dwStackSize, // 初始化线程堆栈尺寸
__in LPTHREAD_START_ROUTINE lpStartAddress, //线程函数所指向的地址 起始函数
__in_opt LPVOID lpParameter, // 给线程函数传递的参数
__in DWORD dwCreationFlags, // 有关线程的标志
__out_opt LPDWORD lpThreadId //系统分配给线程的ID
);
----第一个参数是安全属性,一般设为nil,使用缺省的安全属性。当我们想此线程有另外的子进程时,可改变它的属性。
----第二个参数是线程堆栈尺寸,一般设为0,表示与此应用的堆栈尺寸相同,即主线程与创建的线程一样长度的堆栈。并且其长度会根据需要自动变长。
----第三个参数,也是最重要的一个,是一个指向函数名的指针,但传递时很简单,只需在线程函数名前加上@就可以了。
----第四个参数是你需要向线程函数传递的参数,一般是一个指向结构的指针。不需传递参数时,则这个参数设为nil。
----第五个参数,传入与线程有关的一些标志,如果是CREATE_SUSPENDED,则创建一个挂起的线程,即这个线程本身已创建,它的堆栈也已创建。但这个线程不会被分配给CPU时间,只有当ResumeThread函数被调用后才能执行;当然,也可以调用SuspendThread函数再次挂起线程。要是标志为0,那么一旦建立线程,线程函数就被立即调用。一般传为0即可。
----第六个参数是系统分配给这个线程的唯一的ID标志
// Example.cpp
#include Windows.h
#include iostream
#include string.h
using namespace std;
DWORD WINAPI StartThread(LPVOID iValue)
{
char lszParam[3];
strcpy(lszParam,(char *)iValue);
int iStart = atoi(lszParam);
for(int i=iStart;i=iStart+10;i++)
coutiendl;
return 0;
}
void main()
{
HANDLE hThread1,hThread2;
DWORD dwGenericThread;
char lszThreadParam[3];
strcpy(lszThreadParam,"3");
hThread1 = CreateThread(NULL,0,StartThread,lszThreadParam,0,dwGenericThread);
if(hThread1 == NULL)
{
DWORD dwError = GetLastError();
cout"Error in Creating thread"dwErrorendl ;
return;
}
WaitForSingleObject(hThread1,INFINITE);
//Second thread creation
strcpy(lszThreadParam,"30");
hThread2 = CreateThread(NULL,0,StartThread,lszThreadParam,0,dwGenericThread);
if(hThread1 == NULL)
{
DWORD dwError = GetLastError();
cout"Error in Creating thread"dwErrorendl ;
return;
}
WaitForSingleObject(hThread2,INFINITE);
}