采用_beginthread/_beginthreadex函数创建多线程

1、CRT简介:

CRT: (C Runtime Library)即C运行时库,是系统运行的基础,包含了c常用的函数集(如:printf,malloc,strcpy等),为运行main做了初始化环境变量、堆、io等资源,并在结束后清理。

在Windows环境下,VC提供的 C run-time library又分为动态运行时库、静态运行时库、多线程、单线程、调试版本(Debug)、发行版本(Release)等。

 开关

对应的库

版本

   /MD

MSVCRT.LIB

多线程DLLRelease版本

   /MDd

MSCVRTD.LIB

多线程DLLDebug版本

   /MT

LIBCMT.LIB

多线程静态链接的Release版本

   /MTd

LIBCMTD.LIB

多线程静态链接的Debug版本

   /clr

MSVCMRT.LIB

托管代码和非托管代码混合

   /clr:pure

MSVCURT.LIB

纯托管代码

图1:编译器运行库设置(VS2008)

具体请参考MSDN:

ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_vccrt/html/a889fd39-807d-48f2-807f-81492612463f.htm

2、使用CRT的多线程函数集:两组

序号

函数名

功能

1

_beginthread()

创建一个新线程

2

_endthread()

结束一个线程的执行

3

_beginthreadex()

创建一个新线程

4

_endthreadex()

结束一个线程的执行

5

ResumeThread()

恢复线程的运行

6

SuspendThread()

挂起线程

7

GetExiCodeThread()

得到一个线程的退出码

8

WaitForSingleObject()

等待单个对象

9

WaitForMultipleObjects()

等待多个对象

3、两组函数的说明:

3.1、_beginthread和_endthread
该函数是C Runtime Library中的函数。其原型如下

unsigned long _beginthread(

void( __cdecl *start_address )( void * ),//线程函数的起始地址

unsigned stack_size,//堆栈大小,设置0为系统默认值

void *arglist );//传递给线程函数的参数,没有则为NULL

“该函数被认为是头脑简单的函数”,使用该函数导致无法有效的控制被创建线程,如不能在启动时将该线程挂起,无法为该线程设置优先权等。另外,无法利用这个Handle来等待该线程结束等操作。该函数是早期的C Runtime Library的产物,不提倡使用,后期的改良版本为_beginthreadex。
通过_beginthread启动的线程在应当通过调用_endthread结束,以保证清除与线程相关的资源。_endthread的原型为:

void _endthread(void);

 

3.2、_beginthreadex和_endthreadex
该函数是C Runtime Library中的一个函数,用标准C实现,相比_beginthread,_beginthreadex对线程控制更为有力(比前者多三个参数),是_beginthread的加强版。其原型为:

unsignedlong _beginthreadex(

void *security,//线程函数的安全描述符

unsigned stack_size,// 堆栈大小,设置0为系统默认值

unsigned ( __stdcall *start_address )( void * ),//线程函数的起始地址

void*arglist, //传递给线程函数的参数,没有则为NULL

unsignedinitflag,//初始状态,0为立即执行,CREATE_SUSPEND为创建后挂起

unsigned*thrdaddr );//指向一个32为的变量,存放线程标识符

该函数返回新线程的句柄,通过该句柄可实现对线程的控制。虽然,该函数是用标准C写的(即可不加修改就可以移植到其他系统执行),但是由于它与Windows系统有着紧密的联系(需要手动关闭该线程产生的Handle),因此实现时,往往需要包含windows.h。
通过_beginthreadex启动的线程通过调用_endthreadex做相关清理。该函数比较像CreateThread函数。

_endthreadex函数的原型为:

void _endthreadex(unsigned retVal);

关于这两组函数的详细区别请参考MSDN的说明:

Creates a thread.

uintptr_t _beginthread(

   void( *start_address )( void * ),

   unsigned stack_size,

   void *arglist

);

uintptr_t _beginthreadex(

   void *security,

   unsigned stack_size,

   unsigned ( *start_address )( void * ),

   void *arglist,

   unsigned initflag,

   unsigned *thrdaddr

);

Parameters

start_address

Start address of a routine that begins execution of a new thread.For _beginthread, the calling convention is either__cdecl or __clrcall; for _beginthreadex, it iseither __stdcall or __clrcall.

stack_size

Stack size for a new thread or 0.

arglist

Argument list to be passed to a new thread or NULL.

security

Pointer to a SECURITY_ATTRIBUTES structure that determines whetherthe returned handle can be inherited by child processes. If NULL, the handlecannot be inherited. Must be NULL for Windows 95 applications.

initflag

Initial state of a new thread (0 forrunning or CREATE_SUSPENDED for suspended); useResumeThread to execute the thread.

thrdaddr

Points to a 32-bit variable that receives the thread identifier.Might be NULL, in which case it is not used.

Return Value

If successful, each of these functions returns a handle to thenewly created thread; however, if the newly created thread exits too quickly, _beginthread might not return a valid handle (see thediscussion in the Remarks section). _beginthread returns -1L on an error, in which case errno is set to EAGAIN if thereare too many threads, to EINVAL if the argument isinvalid or the stack size is incorrect, or to EACCESin the case of insufficient resources (such as memory). _beginthreadexreturns 0 on an error, in which case errno and _doserrno are set.

If startaddress is NULL, the invalid parameter handler is invoked, asdescribed in Parameter Validation. If execution is allowed to continue, these functions set errno to EINVAL and return -1.

For more information about these and other return codes, see_doserrno, errno, _sys_errlist, and _sys_nerr.

For more information about uintptr_t,see Standard Types.

Remarks

The _beginthread function creates athread that begins execution of a routine at start_address.The routine at start_address must use the __cdecl calling convention and should have no returnvalue. When the thread returns from that routine, it is terminatedautomatically. For more information about threads, see Multithreading.

_beginthreadex resembles the Win32 CreateThread API more closely than _beginthread does. _beginthreadexdiffers from _beginthread in the following ways:

·        _beginthreadex has three additional parameters: initflag,security, and threadaddr.The new thread can be created in a suspended state, with a specified security(Windows NT only), and can be accessed using thrdaddr,which is the thread identifier.

·        The routine at start_address passed to _beginthreadexmust use the __stdcall calling convention and mustreturn a thread exit code.

·        _beginthreadex returns 0 on failure, rather than -1L.

·        A thread created with _beginthreadex is terminated by a call to _endthreadex.

The _beginthreadex function gives you morecontrol over how the thread is created than _beginthreaddoes. The _endthreadex function is also moreflexible. For example, with _beginthreadex, you canuse security information, set the initial state of the thread (running orsuspended), and get the thread identifier of the newly created thread. You arealso able to use the thread handle returned by _beginthreadexwith the synchronization APIs, which you cannot do with _beginthread.

It is safer to use _beginthreadex than _beginthread. If the thread generated by _beginthread exits quickly, the handle returned to thecaller of _beginthread might be invalid or, worse

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值