启动createthread函数(createthread beginthread)

http://www.itjxue.com  2023-02-22 06:25  来源:未知  点击次数: 

(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);

}

(责任编辑:IT教学网)

更多