共用方式為


_beginthread _beginthreadex

建立執行緒。

重要

這個 API 不能用於 Windows 執行階段執行的應用程式。如需詳細資訊,請參閱 CRT 函式不支援使用 /ZW

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
    傳入新的執行緒的參數清單或空。

  • Security
    指向 SECURITY ATTRIBUTES 結構的指標,用以判斷回傳的處理常式是否可以被子處理程序繼承。 若為空,處理常式無法被繼承。 它對於 Windows 95 應用程式必為空。

  • Initflag
    新的執行緒的初始狀態 (0 為執行, CREATE_SUSPENDED 為暫停) 。使用 ResumeThread 來執行執行緒。

  • Thrdaddr
    指向接受執行緒識別項的 32 位元變數。 可能為 NULL ,此時它不被使用。

傳回值

若成功,每一個這些函式回傳處理常式予新建立的執行緒。然後,如果新建立的執行緒過快離開, _beginthread 可能不會回傳有效的處理常式 (請參閱 Remarks 一節的討論) 。 _beginthread 在發生錯誤時回傳 -1L ,此時 errno 在太多執行緒時會被設置為 EAGAIN ,在參數不合法或堆疊大小不正確會被設置為 EINVAL ,或在資源不足時 (例如記憶體) 被設置為 EACCES 。 _beginthreadex 在發生錯誤時回傳 0 ,此時 errno 和 _doserrno 會被設置。

如果 startaddress 是 NULL ,無效參數處理常式會被調用,如 參數驗證 中所述。 如果允許繼續執行,這些函式將 EINVAL 設置為 errno 並回傳 -1 。

如需更多關於這些和其他回傳碼的資訊,請參閱 _doserrno 、 errno 、 _sys_errlist 、和 _sys_nerr (_doserrno, errno, _sys_errlist, and _sys_nerr)

如需更多關於 uintptr_t 的資訊,請參閱 標準型別 (Standard Types)

備註

_beginthread 函式建立一個執行緒在 start_address 開始執行一個常式。 在 start_address 的常式必須使用 __cdecl (若為本地碼) 或 __clrcall (若為管理碼) 的呼叫慣例並不該有回傳值。 當執行緒從該常式結束,它會自動終止。 如需執行緒模型的詳細資訊,請參閱 多執行緒 (Multithreading)

_beginthreadex 重新組合 Win32 CreateThread API 得比 _beginthread 更緊密。 _beginthreadex 與 _beginthread 在以下方面不同:

  • _beginthreadex 擁有三個額外的參數: initflag 、 security 和 threadaddr 。 新的執行緒可以以指定的安全性 (只有在 Windows NT) 下建立為暫停狀態,並且可以使用執行緒識別項 thrdaddr 存取。

  • 在 start_address ,傳入 _beginthreadex 的常式必須使用 __stdcall (若為本地碼) 或 __clrcall (若為管理碼) 呼叫慣例並且必須回傳一個執行緒終止碼。

  • _beginthreadex 在失敗時回傳 0 ,而非 -1L 。

  • 以 _beginthreadex 建立的執行緒會藉由呼叫 _endthreadex 終止。

比起 _beginthread , _beginthreadex 函式給予您更多執行緒建立方式的控制。 _endthreadex 函式也更有彈性。 例如, 使用 _beginthreadex 時,您可以使用安全性資訊,設置執行緒的初始狀態 (執行或暫停) ,並取得新建立的執行緒的執行緒識別項。 您也可以與同步化的 API 使用 _beginthreadex回傳的執行緒處理常式,這在 _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 必須提供一些值予新執行緒。 如果任何執行緒呼叫 abort 、 exit 、 _exit 或 ExitProcess 時所有的執行緒會被終止。

新的執行緒的地區設定是從父執行緒繼承而來。 如果透過呼叫 _configthreadlocale 來啟用執行緒個別套用地區設定 (全域性或只有新的執行緒) ,執行緒可以透過呼叫 setlocale 或 _wsetlocale 從其父執行緒獨立地改變它的地區設定。 如需詳細資訊,請參閱 地區設定 (Locale)

對於混合或純粹的程式碼, _beginthread 和 _beginthreadex 均有兩種多載版本,其一接受本地呼叫慣例函式指標,另一接受 __clrcall 函式指標。 第一個多載版本不會且永遠不會是應用程式域安全的。 如果您撰寫混合或純粹程式碼,您必須確保新的執行緒在存取管理資源前進入正確的應用程式域。 例如,您可以透過使用 call_in_appdomain 函式 來達成。 第二個多載版本是應用程式域安全的。新建立的執行緒會永遠在 _beginthread 或 _beginthreadex 的呼叫者的應用程式域結束。

需求

程序

必要的標頭檔

_beginthread

<process.h>

_beginthreadex

<process.h>

如需更多關於相容性的資訊,請參閱入門介紹中的 相容性 (Compatibility)

程式庫

僅於 C 執行階段程式庫 (C run-time libraries) 的多執行緒版本。

若要使用 _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 *ch );
void CheckKey( void *dummy );

/* GetRandom returns a random integer between min and max. */
#define GetRandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))

BOOL repeat = TRUE;     /* Global repeat flag and video variable */
HANDLE hStdOut;         /* Handle for console window */
CONSOLE_SCREEN_BUFFER_INFO csbi;    /* Console information structure */

int main()
{
    CHAR    ch = 'A';

    hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );

    /* Get display screen's text row and column information. */
   GetConsoleScreenBufferInfo( hStdOut, &csbi );

    /* Launch CheckKey thread to check for terminating keystroke. */
    _beginthread( CheckKey, 0, NULL );

    /* Loop until CheckKey terminates program. */
    while( repeat )
    {
        /* On first loops, launch character threads. */
        _beginthread( Bounce, 0, (void *) (ch++)  );

        /* Wait one second between loops. */
        Sleep( 1000L );
    }
}

/* CheckKey - Thread to wait for a keystroke, then clear repeat flag. */
void CheckKey( void *dummy )
{
    _getch();
    repeat = 0;    /* _endthread implied */

}

/* Bounce - Thread to create and and control a colored letter that moves
 * around on the screen.
 * Params: ch - the letter to be moved
 */
void Bounce( void *ch )
{
    /* Generate letter and color attribute from thread argument. */
    char    blankcell = 0x20;
    char    blockcell = (char) ch;
    BOOL    first = TRUE;
   COORD   oldcoord, newcoord;
   DWORD   result;


    /* Seed random number generator and get initial location. */
    srand( _threadid );
    newcoord.X = GetRandom( 0, csbi.dwSize.X - 1 );
    newcoord.Y = GetRandom( 0, csbi.dwSize.Y - 1 );
    while( repeat )
    {
        /* Pause between loops. */
        Sleep( 100L );

        /* Blank out our old position on the screen, and draw new letter. */
        if( first )
            first = FALSE;
        else
         WriteConsoleOutputCharacter( hStdOut, &blankcell, 1, oldcoord, &result );
         WriteConsoleOutputCharacter( hStdOut, &blockcell, 1, newcoord, &result );

        /* Increment the coordinate for next placement of the block. */
        oldcoord.X = newcoord.X;
        oldcoord.Y = newcoord.Y;
        newcoord.X += GetRandom( -1, 1 );
        newcoord.Y += GetRandom( -1, 1 );

        /* Correct placement (and beep) if about to go off the screen. */
        if( newcoord.X < 0 )
            newcoord.X = 1;
        else if( newcoord.X == csbi.dwSize.X )
            newcoord.X = csbi.dwSize.X - 2;
        else if( newcoord.Y < 0 )
            newcoord.Y = 1;
        else if( newcoord.Y == csbi.dwSize.Y )
            newcoord.Y = csbi.dwSize.Y - 2;

        /* If not at a screen border, continue, otherwise beep. */
        else
            continue;
        Beep( ((char) ch - 'A') * 100, 175 );
    }
    /* _endthread given to terminate */
    _endthread();
}
  press any key to end

下列範例程式碼展示您如何與同步化 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 );
}
       

.NET Framework 對等用法

System::Threading::Thread::Start

請參閱

參考

處理程序和環境控制

_endthread _endthreadex

abort

exit、_exit

GetExitCodeThread