_beginthread、_beginthreadex_beginthread, _beginthreadex

スレッドを作成します。Creates a thread.

構文Syntax

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

パラメーターParameters

start_addressstart_address
新しいスレッドの実行を開始するルーチンの開始アドレス。Start address of a routine that begins execution of a new thread. _Beginthread の場合、呼び出し規則は __cdecl (ネイティブコードの場合) または __clrcall (マネージコードの場合) のいずれかになります。_beginthreadex の場合、 __stdcall (ネイティブコードの場合) または __clrcall (マネージコードの場合) のいずれかになります。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_sizestack_size
新しいスレッドのスタック サイズまたは 0。Stack size for a new thread, or 0.

arglistarglist
新しいスレッドに渡される引数リストまたは NULLArgument list to be passed to a new thread, or NULL.

SecuritySecurity
SECURITY_ATTRIBUTES 構造体へのポインター。この構造体は、返されたハンドルを子プロセスが継承できるかどうかを決定します。Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. セキュリティNULL の場合、ハンドルを継承することはできません。If Security is NULL, the handle cannot be inherited. Windows 95 アプリケーションの場合は NULL にする必要があります。Must be NULL for Windows 95 applications.

initflaginitflag
新しいスレッドの初期状態を制御するフラグ。Flags that control the initial state of a new thread. Initflag を0に設定して直ちに実行するか、 CREATE_SUSPENDED して中断状態のスレッドを作成します。ResumeThreadを使用してスレッドを実行します。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. InitflagSTACK_SIZE_PARAM_IS_A_RESERVATION フラグに設定して、スタックの初期予約サイズとして stack_size を使用します (バイト単位)。このフラグが指定されていない場合、 stack_size によってコミットサイズが指定されます。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.

thrdaddrthrdaddr
スレッド識別子を受け取る 32 ビット変数へのポインター。Points to a 32-bit variable that receives the thread identifier. NULL の場合は使用されません。If it's NULL, it's not used.

戻り値Return Value

成功した場合、これらの各関数は、新しく作成されたスレッドへのハンドルを返します。ただし、新しく作成されたスレッドが短時間で終了した場合、 _beginthread は有効なハンドルを返さない可能性があります。If successful, each of these functions returns a handle to the newly created thread; however, if the newly created thread exits too quickly, _beginthread might not return a valid handle. (「解説」の説明を参照してください)。エラーが発生すると、 _beginthread は-1l を返し、スレッドの数が多すぎる場合は EAGAIN に設定され、引数が無効であるかスタックサイズが 正しくない場合 は EACCES、不足しているリソース (メモリなど) がある場合はに設定 されます(See the discussion in the Remarks section.) On an error, _beginthread returns -1L, and errno is set to EAGAIN if there are too many threads, to EINVAL if the argument is invalid or the stack size is incorrect, or to EACCES if there are insufficient resources (such as memory). エラーが発生した場合、 _beginthreadex は0を返し、 errno_doserrno が設定されます。On an error, _beginthreadex returns 0, and errno and _doserrno are set.

Start_addressNULL の場合は、「パラメーターの検証」で説明されているように、無効なパラメーターハンドラーが呼び出されます。If start_address is NULL, the invalid parameter handler is invoked, as described in Parameter Validation. 実行の継続が許可された場合、これらの関数は errnoEINVAL に設定し、-1 を返します。If execution is allowed to continue, these functions set errno to EINVAL and return -1.

これらのリターン コードとその他のリターン コードの詳細については、「errno、_doserrno、_sys_errlist、および _sys_nerr」を参照してください。For more information about these and other return codes, see errno, _doserrno, _sys_errlist, and _sys_nerr.

Uintptr_t の詳細については、「標準型」を参照してください。For more information about uintptr_t, see Standard Types.

解説Remarks

_Beginthread 関数は、 start_address でルーチンの実行を開始するスレッドを作成します。The _beginthread function creates a thread that begins execution of a routine at start_address. Start_address のルーチンは、 __cdecl (ネイティブコードの場合) または __clrcall (マネージコードの場合) の呼び出し規約を使用する必要があり、戻り値を持つことはできません。The routine at start_address must use the __cdecl (for native code) or __clrcall (for managed code) calling convention and should have no return value. スレッドは、ルーチンから戻ると自動的に終了します。When the thread returns from that routine, it is terminated automatically. スレッドの詳細については、「旧形式のコードのためのマルチスレッド サポート (Visual C++)」を参照してください。For more information about threads, see Multithreading Support for Older Code (Visual C++).

_beginthreadex は、 _beginthread よりも厳密に Win32 CreateThread API に似ています。_beginthreadex resembles the Win32 CreateThread API more closely than _beginthread does. _beginthreadex は、次の方法で _beginthread とは異なります。_beginthreadex differs from _beginthread in the following ways:

  • _beginthreadex には、 initflagSecuritythreadaddr という3つの追加パラメーターがあります。_beginthreadex has three additional parameters: initflag, Security, and threadaddr. 新しいスレッドは、指定されたセキュリティを使用して中断状態で作成でき、スレッド識別子である thrdaddr を使用してアクセスできます。The new thread can be created in a suspended state, with a specified security, and can be accessed by using thrdaddr, which is the thread identifier.

  • _Beginthreadex に渡される start_address のルーチンは、 __stdcall (ネイティブコードの場合) または __clrcall (マネージコードの場合) の呼び出し規約を使用する必要があり、スレッドの終了コードを返す必要があります。The routine at start_address that's passed to _beginthreadex must use the __stdcall (for native code) or __clrcall (for managed code) calling convention and must return a thread exit code.

  • _beginthreadex は、-1l ではなく、エラーが発生した場合は0を返します。_beginthreadex returns 0 on failure, rather than -1L.

  • _Beginthreadex を使用して作成されたスレッドは、 _endthreadexの呼び出しによって終了します。A thread that's created by using _beginthreadex is terminated by a call to _endthreadex.

_Beginthreadex 関数を使用すると、 _beginthread よりもスレッドの作成方法をより詳細に制御できます。The _beginthreadex function gives you more control over how the thread is created than _beginthread does. _Endthreadex 関数もより柔軟です。The _endthreadex function is also more flexible. たとえば、 _beginthreadex を使用すると、セキュリティ情報の使用、スレッドの初期状態 (実行中または中断) の設定、新しく作成されたスレッドのスレッド識別子の取得を行うことができます。For example, with _beginthreadex, you can use security information, set the initial state of the thread (running or suspended), and get the thread identifier of the newly created thread. _Beginthreadex によって返されたスレッドハンドルを同期 api と共に使用することもできます。この場合、 _beginthread を使用することはできません。You can also use the thread handle that's returned by _beginthreadex with the synchronization APIs, which you cannot do with _beginthread.

_Beginthread よりも _beginthreadex を使用する方が安全です。It's safer to use _beginthreadex than _beginthread. _Beginthread によって生成されるスレッドが短時間で終了した場合は、 _beginthread の呼び出し元に返されるハンドルが無効であるか、別のスレッドを指している可能性があります。If the thread that's generated by _beginthread exits quickly, the handle that's returned to the caller of _beginthread might be invalid or point to another thread. ただし、 _beginthreadex によって返されるハンドルは _beginthreadex の呼び出し元によって閉じられる必要があるため、 _beginthreadex がエラーを返さなかった場合は、有効なハンドルであることが保証されます。However, the handle that's returned by _beginthreadex has to be closed by the caller of _beginthreadex, so it is guaranteed to be a valid handle if _beginthreadex did not return an error.

_Endthreadまたは _endthreadex を明示的に呼び出してスレッドを終了できます。ただし、 _endthread または _endthreadex は、パラメーターとして渡されたルーチンからスレッドが戻ったときに、自動的に呼び出されます。You can call _endthread or _endthreadex explicitly to terminate a thread; however, _endthread or _endthreadex is called automatically when the thread returns from the routine that's passed as a parameter. _Endthread または _endthreadex の呼び出しを使用してスレッドを終了すると、スレッドに割り当てられているリソースを正しく回復できます。Terminating a thread with a call to _endthread or _endthreadex helps ensure correct recovery of resources that are allocated for the thread.

_endthread はスレッドハンドルを自動的に閉じるのに対し、 _endthreadex は自動的に終了します。_endthread automatically closes the thread handle, whereas _endthreadex does not. したがって、 _beginthread_endthread を使用する場合は、Win32 CloseHandle API を呼び出してスレッドハンドルを明示的に終了しないでください。Therefore, when you use _beginthread and _endthread, do not explicitly close the thread handle by calling the Win32 CloseHandle API. この動作は、Win32 ExitThread API とは異なります。This behavior differs from the Win32 ExitThread API.

注意

Libcmt.lib にリンクされている実行可能ファイルの場合、Win32 Exitthread API を呼び出さないでください。これにより、割り当てられたリソースをランタイムシステムで再利用できなくなります。For an executable file linked with Libcmt.lib, do not call the Win32 ExitThread API so that you don't prevent the run-time system from reclaiming allocated resources. _endthread_endthreadex は、割り当てられているスレッドリソースを解放し、 exitthread を呼び出します。_endthread and _endthreadex reclaim allocated thread resources and then call ExitThread.

_Beginthread または _beginthreadex のいずれかが呼び出されると、オペレーティングシステムはスタックの割り当てを処理します。スレッドスタックのアドレスをこれらの関数のいずれかに渡す必要はありません。The operating system handles the allocation of the stack when either _beginthread or _beginthreadex is called; you don't have to pass the address of the thread stack to either of these functions. また、 stack_size 引数を0にすることもできます。この場合、オペレーティングシステムはメインスレッドに指定されているスタックと同じ値を使用します。In addition, the stack_size argument can be 0, in which case the operating system uses the same value as the stack that's specified for the main thread.

arglist は、新しく作成されたスレッドに渡すパラメーターです。arglist is a parameter to be passed to the newly created thread. 通常、文字列などのデータ項目のアドレスを指定します。Typically, it is the address of a data item, such as a character string. arglist は、不要な場合は NULL にすることができますが、 _beginthread_beginthreadex には、新しいスレッドに渡す値を指定する必要があります。arglist can be NULL if it is not needed, but _beginthread and _beginthreadex must be given some value to pass to the new thread. いずれかのスレッドが abortexit_exit、または ExitProcess を呼び出すと、すべてのスレッドが終了します。All threads are terminated if any thread calls abort, exit, _exit, or ExitProcess.

新しいスレッドのロケールは、プロセスごとのグローバル現在のロケール情報を使用して初期化されます。The locale of the new thread is initialized by using the per-process global current locale info. _Configthreadlocaleを呼び出すことによってスレッドごとのロケールが有効になっている場合 (グローバルまたは新しいスレッドのみ)、スレッドは setlocale または _wsetlocale を呼び出すことによって、他のスレッドとは別にロケールを変更できます。If per-thread locale is enabled by a call to _configthreadlocale (either globally or for new threads only), the thread can change its locale independently from other threads by calling setlocale or _wsetlocale. スレッドごとのロケールフラグが設定されていないスレッドは、スレッドごとのロケールフラグが設定されていない他のすべてのスレッドのロケール情報や、新しく作成されたすべてのスレッドのロケール情報に影響を与える可能性があります。Threads that don't have the per-thread locale flag set can affect the locale info in all other threads that also don't have the per-thread locale flag set, as well as all newly-created threads. 詳細については、「 Locale」を参照してください。For more information, see Locale.

/Clr コードの場合、 _beginthread_beginthreadex にはそれぞれ2つのオーバーロードがあります。For /clr code, _beginthread and _beginthreadex each have two overloads. 一方はネイティブの呼び出し規約関数ポインターを受け取り、もう1つは __clrcall 関数ポインターを受け取ります。One takes a native calling-convention function pointer, and the other takes a __clrcall function pointer. 最初のオーバーロードは、アプリケーション ドメインセーフではなく、以降もそうなることはありません。The first overload is not application domain-safe and never will be. /Clr コードを記述する場合は、新しいスレッドがマネージリソースにアクセスする前に正しいアプリケーションドメインに入るようにする必要があります。If you are writing /clr code you must ensure that the new thread enters the correct application domain before it accesses managed resources. そのためには、call_in_appdomain 関数などを使用します。You can do this, for example, by using call_in_appdomain Function. 2番目のオーバーロードは、アプリケーションドメインセーフです。新しく作成されたスレッドは常に、 _beginthread または _beginthreadex の呼び出し元のアプリケーションドメインで終了します。The second overload is application domain-safe; the newly created thread will always end up in the application domain of the caller of _beginthread or _beginthreadex.

既定では、この関数のグローバル状態はアプリケーションにスコープが設定されています。By default, this function's global state is scoped to the application. これを変更するには、「 CRT でのグローバル状態」を参照してください。To change this, see Global state in the CRT.

必要条件Requirements

ルーチンによって返される値Routine 必須ヘッダーRequired header
_beginthread_beginthread <process.h>
_beginthreadex_beginthreadex <process.h>

互換性について詳しくは、「 Compatibility」をご覧ください。For more compatibility information, see Compatibility.

ライブラリLibraries

C ランタイム ライブラリ のマルチスレッド バージョンのみ。Multithreaded versions of the C run-time libraries only.

_Beginthread または _beginthreadex を使用するには、アプリケーションをマルチスレッドの C ランタイムライブラリの1つにリンクする必要があります。To use _beginthread or _beginthreadex, the application must link with one of the multithreaded C run-time libraries.

Examples

次の例では、 _beginthread_endthread を使用します。The following example uses _beginthread and _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.
        else
            continue;
        Beep((ci.Char.AsciiChar - 'A') * 100, 175);
    }
    // _endthread given to terminate
    _endthread();
}

任意のキーを押してサンプル アプリケーションを終了します。Press any key to end the sample application.

次のサンプルコードは、 _beginthreadex によって返されたスレッドハンドルを同期 API WaitForSingleObjectと共に使用する方法を示しています。The following sample code demonstrates how you can use the thread handle that's returned by _beginthreadex with the synchronization API WaitForSingleObject. メイン スレッドは、2 番目のスレッドが終了するのを待って処理を継続します。The main thread waits for the second thread to terminate before it continues. 2番目のスレッドが _endthreadex を呼び出すと、そのスレッドオブジェクトがシグナル状態になります。When the second thread calls _endthreadex, it causes its thread object to go to the signaled state. これにより、1 番目のスレッドの実行が継続されます。This allows the primary thread to continue running. これは _beginthread_endthread では実行できません。これは、 _endthreadCloseHandle を呼び出し、スレッドオブジェクトがシグナル状態に設定される前に破棄されるためです。This cannot be done with _beginthread and _endthread, because _endthread calls CloseHandle, which destroys the thread object before it can be set to the signaled state.

// 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

関連項目See also