语法

uintptr_t _beginthread( // NATIVE CODEvoid( __cdecl *start_address )( void * ),unsigned stack_size,void *arglist
);
uintptr_t _beginthread( // MANAGED CODEvoid( __clrcall *start_address )( void * ),unsigned stack_size,void *arglist
);
uintptr_t _beginthreadex( // NATIVE CODEvoid *security,unsigned stack_size,unsigned ( __stdcall *start_address )( void * ),void *arglist,unsigned initflag,unsigned *thrdaddr
);
uintptr_t _beginthreadex( // MANAGED CODEvoid *security,unsigned stack_size,unsigned ( __clrcall *start_address )( void * ),void *arglist,unsigned initflag,unsigned *thrdaddr
);

参数

start_address

开始执行新线程的实例的起始地址。对于_beginthread,调用约定是__cdecl(对于本机代码)或__clrcall(对于托管代码);
对于_beginthreadex,它是__stdcall(对于本机代码)或__clrcall(对于托管代码)。

Start address of a routine that begins execution of a new thread. For _beginthread, the calling convention is either __cdecl (for native code) or __clrcall (for managed code); for _beginthreadex, it is either __stdcall (for native code) or __clrcall (for managed code).

stack_size

新线程的堆栈大小,或为0。

Stack size for a new thread, or 0.

arglist

要传递给新线程的参数列表,或者为NULL。

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

Security

指向SECURITY_ATTRIBUTES结构的安全指针,该结构确定返回的句柄是否可以由子进程继承。如果Security为NULL,则不能继承该句柄。对于Windows 95应用程序,必须为NULL。

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

initflag

用于控制新线程的初始状态的标志。将initflag设置为0可立即运行,或将CREATE_SUSPENDED设置为处于挂起状态的线程;使用ResumeThread执行线程。
将initflag设置为STACK_SIZE_PARAM_IS_A_RESERVATION标志,以使用stack_size作为堆栈的初始保留大小(以字节为单位);如果未指定此标志,则stack_size指定提交大小。

Flags that control the initial state of a new thread. Set initflag to 0 to run immediately, or to CREATE_SUSPENDED to create the thread in a suspended state; use ResumeThread to execute the thread. Set initflag to STACK_SIZE_PARAM_IS_A_RESERVATION flag to use stack_size as the initial reserve size of the stack in bytes; if this flag is not specified, stack_size specifies the commit size.

thrdaddr

指向接收线程标识符的32位变量。如果为NULL,则不使用。

Points to a 32-bit variable that receives the thread identifier. If it’s NULL, it’s not used.

返回值

如果成功,则这些函数中的每个函数都会为新创建的线程返回一个句柄。但是,如果新创建的线程退出太快,则_beginthread可能不会返回有效的句柄。(见备注部分的讨论。)上的错误,_beginthread返回-1L,并且将errno设置为EAGAIN如果有太多的线程,以EINVAL如果参数无效或堆栈大小是不正确,或EACCES如果没有足够的资源(例如内存)。发生错误时,_beginthreadex返回0,并设置了errno和_doserrno。

如果start_address为NULL,则将调用无效的参数处理程序,如Parameter Validation中所述。如果允许执行继续,这些函数会将errno设置为EINVAL并返回-1。

有关这些代码和其他返回代码的更多信息,请参见errno,_doserrno,_sys_errlist和_sys_nerr。

有关uintptr_t的更多信息,请参见“ 标准类型”。

备注

该_beginthread函数创建,在开始例行的执行线程START_ADDRESS。start_address处的例程必须使用__cdecl(对于本机代码)或__clrcall(对于托管代码)调用约定,并且不应具有任何返回值。当线程从该例程返回时,它将自动终止。有关线程的更多信息,请参见旧代码的多线程支持(Visual C ++)。

_beginthreadex类似的Win32 的CreateThread更加紧密地比API _beginthread一样。_beginthreadex与_beginthread在以下方面有所不同:

_beginthreadex具有三个附加参数:initflag,Security和threadaddr。可以以指定的安全性在挂起状态下创建新线程,并可以使用thrdaddr(线程标识符)对其进行访问。

传递给_beginthreadex的start_address上的例程必须使用__stdcall(对于本机代码)或__clrcall(对于托管代码)调用约定,并且必须返回线程退出代码。

_beginthreadex失败时返回0,而不是-1L。

使用_beginthreadex创建的线程会通过调用_endthreadex终止。

该_beginthreadex功能为您提供了更多的控制权的线程是如何创建比_beginthread一样。该_endthreadex功能也更加灵活。例如,使用_beginthreadex,您可以使用安全性信息,设置线程的初始状态(运行或暂停),并获取新创建的线程的线程标识符。您还可以将_beginthreadex返回的线程句柄与同步API一起使用,而_beginthread则不能使用。

使用_beginthreadex比_beginthread更安全。如果_beginthread生成的线程快速退出,则返回给_beginthread调用者的句柄可能无效或指向另一个线程。但是,这是由返回的句柄_beginthreadex必须由调用者关闭_beginthreadex,所以它是保证一个有效的句柄,如果_beginthreadex没有返回一个错误。

您可以显式调用_endthread或_endthreadex来终止线程。但是,当线程从作为参数传递的例程返回时,会自动调用_endthread或_endthreadex。通过调用_endthread或_endthreadex终止线程有助于确保正确恢复分配给该线程的资源。

_endthread自动关闭线程句柄,而_endthreadex则不会。因此,当您使用_beginthread和_endthread时,不要通过调用Win32 CloseHandle API 显式关闭线程句柄。此行为不同于Win32 ExitThread API。

注意 对于链接到Libcmt.lib的可执行文件,请不要调用Win32 ExitThread API,这样就不会阻止运行时系统回收分配的资源。_endthread和_endthreadex回收分配的线程资源,然后调用ExitThread。】

调用_beginthread或_beginthreadex时,操作系统会处理堆栈的分配。您不必将线程堆栈的地址传递给这两个函数。另外,stack_size参数可以为0,在这种情况下,操作系统使用与为主线程指定的堆栈相同的值。

arglist是要传递给新创建的线程的参数。通常,它是数据项的地址,例如字符串。如果不需要,arglist可以为NULL,但是_beginthread和_beginthreadex必须提供一些值才能传递给新线程。如果任何线程调用中止,退出,_exit或ExitProcess,则终止所有线程。

通过使用每个进程的全局当前语言环境信息来初始化新线程的语言环境。如果通过调用_configthreadlocale(全局或仅用于新线程)启用了每个线程的语言环境,则该线程可以通过调用setlocale或_wsetlocale来独立于其他线程来更改其语言环境。没有设置每线程语言环境标志的线程会影响所有其他没有设置每线程语言环境标志的线程的语言环境信息,以及所有新创建的线程。有关更多信息,请参见语言环境。

对于/ clr代码,_beginthread和_beginthreadex每个都有两个重载。一个采用本机调用约定函数指针,而另一个采用__clrcall函数指针。第一次重载不是应用程序域安全的,永远不会。如果要编写/ clr代码,则必须确保新线程在访问托管资源之前进入正确的应用程序域。您可以例如通过使用call_in_appdomain Function来执行此操作。第二重载是应用程序域安全的;新创建的线程将始终以_beginthread或_beginthreadex的调用者的应用程序域结尾。

例子

以下示例使用_beginthread和_endthread。

// crt_BEGTHRD.C
// compile with: /MT /D "_X86_" /c
// processor: x86
#include <windows.h>
#include <process.h>    /* _beginthread, _endthread */
#include <stddef.h>
#include <stdlib.h>
#include <conio.h>void Bounce( void * );
void CheckKey( void * );// GetRandom returns a random integer between min and max.
#define GetRandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))
// GetGlyph returns a printable ASCII character value
#define GetGlyph( val ) ((char)((val + 32) % 93 + 33))BOOL repeat = TRUE;                 // Global repeat flag
HANDLE hStdOut;                     // Handle for console window
CONSOLE_SCREEN_BUFFER_INFO csbi;    // Console information structureint main()
{int param = 0;int * pparam = &param;// Get display screen's text row and column information.hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );GetConsoleScreenBufferInfo( hStdOut, &csbi );// Launch CheckKey thread to check for terminating keystroke._beginthread( CheckKey, 0, NULL );// Loop until CheckKey terminates program or 1000 threads created.while( repeat && param < 1000 ){// launch another character thread._beginthread( Bounce, 0, (void *) pparam );// increment the thread parameterparam++;// Wait one second between loops.Sleep( 1000L );}
}// CheckKey - Thread to wait for a keystroke, then clear repeat flag.
void CheckKey( void * ignored )
{_getch();repeat = 0;    // _endthread implied
}// Bounce - Thread to create and control a colored letter that moves
// around on the screen.
//
// Params: parg - the value to create the character from
void Bounce( void * parg )
{char       blankcell = 0x20;CHAR_INFO  ci;COORD      oldcoord, cellsize, origin;DWORD      result;SMALL_RECT region;cellsize.X = cellsize.Y = 1;origin.X = origin.Y = 0;// Generate location, letter and color attribute from thread argument.srand( _threadid );oldcoord.X = region.Left = region.Right =GetRandom(csbi.srWindow.Left, csbi.srWindow.Right - 1);oldcoord.Y = region.Top = region.Bottom =GetRandom(csbi.srWindow.Top, csbi.srWindow.Bottom - 1);ci.Char.AsciiChar = GetGlyph(*((int *)parg));ci.Attributes = GetRandom(1, 15);while (repeat){// Pause between loops.Sleep( 100L );// Blank out our old position on the screen, and draw new letter.WriteConsoleOutputCharacterA(hStdOut, &blankcell, 1, oldcoord, &result);WriteConsoleOutputA(hStdOut, &ci, cellsize, origin, &region);// Increment the coordinate for next placement of the block.oldcoord.X = region.Left;oldcoord.Y = region.Top;region.Left = region.Right += GetRandom(-1, 1);region.Top = region.Bottom += GetRandom(-1, 1);// Correct placement (and beep) if about to go off the screen.if (region.Left < csbi.srWindow.Left)region.Left = region.Right = csbi.srWindow.Left + 1;else if (region.Right >= csbi.srWindow.Right)region.Left = region.Right = csbi.srWindow.Right - 2;else if (region.Top < csbi.srWindow.Top)region.Top = region.Bottom = csbi.srWindow.Top + 1;else if (region.Bottom >= csbi.srWindow.Bottom)region.Top = region.Bottom = csbi.srWindow.Bottom - 2;// If not at a screen border, continue, otherwise beep.elsecontinue;Beep((ci.Char.AsciiChar - 'A') * 100, 175);}// _endthread given to terminate_endthread();
}

以下示例代码演示了如何通过同步API WaitForSingleObject使用_beginthreadex返回的线程句柄。主线程在继续之前等待第二个线程终止。当第二个线程调用_endthreadex时,它将导致其线程对象进入信号状态。这允许主线程继续运行。不能使用_beginthread和_endthread来完成此操作,因为_endthread调用CloseHandle,它会在可以将其设置为信号状态之前破坏线程对象。

// crt_begthrdex.cpp
// compile with: /MT
#include <windows.h>
#include <stdio.h>
#include <process.h>unsigned Counter;
unsigned __stdcall SecondThreadFunc( void* pArguments )
{printf( "In second thread...\n" );while ( Counter < 1000000 )Counter++;_endthreadex( 0 );return 0;
}int main()
{HANDLE hThread;unsigned threadID;printf( "Creating second thread...\n" );// Create the second thread.hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );// Wait until second thread terminates. If you comment out the line// below, Counter will not be correct because the thread has not// terminated, and Counter most likely has not been incremented to// 1000000 yet.WaitForSingleObject( hThread, INFINITE );printf( "Counter should be 1000000; it is-> %d\n", Counter );// Destroy the thread object.CloseHandle( hThread );
}

参考自 _beginthread,_beginthreadex

_beginthread, _beginthreadex相关推荐

  1. Creatthread _Beginthread _Beginthreadex

    在 Win32 API 中,创建线程的基本函数是 CreateThread,而 _beginthread(ex) 是 C++ 运行库的函数.为什么要有两个呢?因为C++ 运行库里面有一些函数使用了全局 ...

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

    1.CRT简介: CRT: (C Runtime Library)即C运行时库,是系统运行的基础,包含了c常用的函数集(如:printf,malloc,strcpy等),为运行main做了初始化环境变 ...

  3. VC++ MSDN中的 _beginthreadex与_endthreadex 的使用例子

    1._beginthread, _beginthreadex . 用于创建线程 [cpp] view plaincopy uintptr_t _beginthread( void( *start_ad ...

  4. CreateThread、_beginthread与AfxBeginThread的区别及其注意事项

    在windows下一般由以下三种方式来进行线程操作: 1.通过CreateThread(),对应线程结束函数ExitThread(): 2.通过_beginthread(),对应线程结束函_endth ...

  5. CreateThread、_beginthreadex和AfxBeginThread 的区别

    CreateThread._beginthreadex和AfxBeginThread 创建线程好几个函数可以使用,可是它们有什么区别,适用于什么情况呢? 参考了一些资料,写得都挺好的,这里做一些摘抄和 ...

  6. _beginthreadex和_endthreadex源码概览

    _beginthreadex是ucrt提供的创建线程的接口,_beginthreadex在内部调用了windows系统提供的CreateThread接口,_endthreadex的作用是显式的结束线程 ...

  7. c++创建线程:CreateThread 和pthread_create和 _beginthreadex

    CreateThread 在 Windows 中,您可以使用 CreateThread() 来创建线程,创建的线程在调用进程的虚拟地址空间中运行.  HANDLE CreateThread(   LP ...

  8. 程序员的自我修养--链接、装载与库笔记:运行库

    1. 入口函数和程序初始化 程序从main开始吗?:操作系统装载程序之后,首先运行的代码并不是main的第一行,而是某些别的代码,这些代码负责准备好main函数执行所需要的环境,并且负责调用main函 ...

  9. Win32 多线程的创建方法,区别和联系

    2019独角兽企业重金招聘Python工程师标准>>> Win32多线程的创建方法主要有: CreateThread() _beginthread()&&_begin ...

  10. 基于MFC串口编程和曲线图绘制(visual studio2008,Teechart绘图控件)的程序总结

    前言 今年刚进入公司按经理的要求为底盘测控机写了一个小小的console.这也是第一次教认真的完成整个程序的编写.程序不大,所用技术比较基础也不前卫,属于初级程序员的练手程序(知识的整理和搬运).虽然 ...

最新文章

  1. Linux 系统目录结构
  2. VS2013+opencv2.4.9配置步骤详解
  3. 为什么我们做分布式的使用都是用Redis?
  4. 也来盘点一些最近的非Transformer工作
  5. 编写程序判断两个数组是否相等,然后编写一段类似的程序比较两个 vector。
  6. 前端学习(1812):前端调试之shadow
  7. C#设计模式之3-建造者模式
  8. 微信小程序支付返回信息为空
  9. [HDOJ]1001. Sum Problem
  10. win10下乌龟git安装和使用
  11. 即拿即用-Android单线程断点下载
  12. 谷歌浏览器html插件字体大小,字体换加插件,自定义Chrome网页字体,更改字体样式,调整字体大小...
  13. MTK G-sensor 1
  14. 山东CIO智库——山东省两化融合深度行龙口站成功举办
  15. 黑市最流行的黑客匿名工具
  16. 前端面试之浏览器/HTML/CSS问题
  17. android 六边形简书,水波浪贝塞尔效果(六边形)
  18. 计算机控制实验报告组态软件学习,中北大学组态软件实验报告
  19. 写给大一充实,大二不顺,大三迷茫的同学
  20. 当你对成功的渴望足以与你对呼吸的渴望相媲美的时候,你就会成功!

热门文章

  1. 小程序开发解决方案_小程序开发方案怎么写
  2. sliksvn下载与安装
  3. 整理了一些大数据资料与电子书,免费分享给大家!!
  4. RoboWare Studio:简介
  5. 二路归并排序的C++实现
  6. 测试学习——全链路压测
  7. linux压力测试脚本,一种基于shell脚本的CPU压力测试方法与流程
  8. 数字化审图时代批量生成PDF或者DWF利器SmartBatchPlot
  9. JQuery AJAX 的表单提交
  10. Activiti7使用