添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
善良的红茶  ·  SQLPrepare 函数 - ODBC ...·  4 周前    · 
侠义非凡的毛衣  ·  BlurXTerminator ...·  3 月前    · 
不拘小节的菠萝  ·  TypeError: sequence ...·  3 月前    · 
低调的红豆  ·  MySQL DBA必备:MySQL ...·  4 月前    · 
有情有义的领带  ·  中国新闻网·  5 月前    · 
uintptr_t _beginthread( // NATIVE CODE
   void( __cdecl *start_address )( void * ),
   unsigned stack_size,
   void *arglist
uintptr_t _beginthread( // MANAGED CODE
   void( __clrcall *start_address )( void * ),
   unsigned stack_size,
   void *arglist
uintptr_t _beginthreadex( // NATIVE CODE
   void *security,
   unsigned stack_size,
   unsigned ( __stdcall *start_address )( void * ),
   void *arglist,
   unsigned initflag,
   unsigned *thrdaddr
uintptr_t _beginthreadex( // MANAGED CODE
   void *security,
   unsigned stack_size,
   unsigned ( __clrcall *start_address )( void * ),
   void *arglist,
   unsigned initflag,
   unsigned *thrdaddr

start_address
启动开始执行新线程的例程的地址。 对于 _beginthread,调用约定要么 __cdecl 是本机代码) (, __clrcall 要么是托管代码) (。 对于 _beginthreadex,调用约定要么 __stdcall 是本机代码) (, __clrcall 要么是托管代码) (。

stack_size
新线程的堆栈大小或 0。

arglist
要传递到新线程的参数列表或 NULL

Security
指向 SECURITY_ATTRIBUTES 结构的指针,此结构确定返回的句柄是否由子进程继承。 如果 SecurityNULL,则无法继承句柄。

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

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

如果成功,则这些函数中的每一个都会返回一个句柄到新创建的线程;但是,如果新创建的线程退出过快,则 _beginthread 可能不会返回有效句柄。 (请参见“备注”部分中的讨论。)发生错误时,_beginthread 返回 -1L,并在线程过多的情况下将 errno 设置为 EAGAIN;如果参数无效或堆栈大小错误,则设置为 EINVAL;如果资源(如内存)不足,则设置为 EACCES。 发生错误时, _beginthreadex 返回 0 并设置 errno_doserrno

如果 start_addressNULL,则调用无效参数处理程序,如 参数验证中所述。 如果允许执行继续,则这些功能将 errno 设置为 EINVAL 并返回 -1。

有关这些返回代码和其他返回代码的详细信息,请参阅 errno_doserrno_sys_errlist_sys_nerr

有关 的详细信息 uintptr_t,请参阅 标准类型

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

_beginthread 相比,_beginthreadex 更类似于 Win32 CreateThread API。 _beginthreadex_beginthread 的差别体现在以下方面:

  • _beginthreadex 还有三个参数: initflagSecuritythreadaddr。 新线程可通过指定的 security 创建为挂起状态,并且可使用线程标识符 thrdaddr进行访问。

  • start_address 处传递给 _beginthreadex 的例程必须使用 __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 是传递到新创建的线程的参数。 通常,它是数据项(如字符串)的地址。 arglistNULL如果不需要,可以为 ,但_beginthread必须为 和 _beginthreadex 提供一些值才能传递给新线程。 如果任何线程调用 abortexit_exitExitProcess,所有线程都会终止。

    新线程的区域设置通过使用每进程全局当前区域设置信息来初始化。 如果通过对 _configthreadlocale 的调用(全局或仅针对新线程)启用了每线程区域设置,则线程可以通过调用 setlocale_wsetlocale 独立从其他线程更改区域设置。 未设置每线程区域设置标志的线程可能会影响所有其他未设置每线程区域设置标志的线程以及所有新创建的线程中的区域设置信息。 有关详细信息,请参阅 Locale

    对于 /clr 代码,_beginthread_beginthreadex 都有两个重载。 一个采用本机调用约定函数指针,另一个采用 __clrcall 函数指针。 第一个重载不是应用程序域安全的,并且永远不会是。 如果要编写 /clr 代码,必须确保新线程在访问托管资源之前进入正确的应用程序域。 例如, call_in_appdomain可以使用 执行此操作。 第二个重载是应用程序安全域;新创建的线程总是在 _beginthread_beginthreadex调用方的应用程序域中结束。

    默认情况下,此函数的全局状态范围限定为应用程序。 若要更改此行为,请参阅 CRT 中的全局状态

    例程所返回的值 必需的标头

    若要使用 _beginthread_beginthreadex,应用程序必须与一个多线程 C 运行库链接。

    下面的示例使用 _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 structure
    int 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 parameter
            param++;
            // 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.
                continue;
            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 );
    
    Creating second thread...
    In second thread...
    Counter should be 1000000; it is-> 1000000
    
  • 进程和环境控制
  • _endthread, _endthreadex
  • abort
  • exit, _Exit, _exit
  • GetExitCodeThread
  •