_beginthread, _beginthreadex

29016 ワード

構文
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(管理コードの場合).
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は-1 Lを返し、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類似のWin 32のCreateThreadはAPI_beginthreadと同じです._beginthreadexと_beginthreadは、次の点で異なります.
_beginthreadexには、initflag、Security、threadadddrの3つの追加パラメータがあります.指定したセキュリティで保留中に新しいスレッドを作成し、thrdaddr(スレッド識別子)を使用してアクセスできます.
に渡すbeginthreadexのstart_addressのインスタンスは__を使用する必要があります.stdcall(ネイティブコードの場合)または__clrcall(管理コードの場合)は、規則を呼び出し、スレッド終了コードを返す必要があります.
_beginthreadexが失敗した場合は-1 Lではなく0を返します.
使用_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の場合、Win 32 CloseHandle APIを呼び出してスレッドハンドルを明示的に閉じないでください.この動作はWin 32 ExitThread APIとは異なります.
【注意Libcmt.libにリンクされた実行可能ファイルについては、Win 32 ExitThread APIを呼び出さないでください.これにより、実行時にシステムが割り当てられたリソースを回収することは阻止されません._endthreadおよび_endthreadexは、割り当てられたスレッドリソースを回収し、ExitThreadを呼び出します.】
呼び出し_beginthreadまたは_beginthreadexの場合、オペレーティングシステムはスタックの割り当てを処理します.この2つの関数にスレッドスタックのアドレスを渡す必要はありません.また、stack_sizeパラメータは0であり、この場合、オペレーティングシステムは、メインスレッドで指定したスタックと同じ値を使用します.
Arglistは、新しく作成したスレッドに渡すパラメータです.通常、文字列などのデータ・アイテムのアドレスです.必要でない場合、arglistはNULLにすることができますが、_beginthreadと_beginthreadexは、新しいスレッドに渡すためにいくつかの値を指定する必要があります.スレッド呼び出しが中止された場合、終了します.exitまたはExitProcessでは、すべてのスレッドが終了します.
各プロセスのグローバル現在の言語環境情報を使用して、新しいスレッドの言語環境を初期化します.呼び出しによって_configthreadlocale(グローバルまたは新規スレッドのみ)各スレッドの言語環境が有効になっている場合、setlocaleまたは_wsetlocaleを呼び出すことで、他のスレッドとは独立して言語環境を変更できます.各スレッドの言語環境フラグを設定していないスレッドは、各スレッドの言語環境フラグを設定していない他のすべてのスレッドの言語環境情報、および新しく作成されたすべてのスレッドに影響します..詳細については、「言語環境」を参照してください.
/clrコードの場合、beginthreadと_beginthreadexにはそれぞれ2つのリロードがあります.一方はネイティブ呼び出し規則関数ポインタを用い,他方は__を用いる.clrcall関数ポインタ.最初のリロードはアプリケーションドメインが安全ではなく、永遠にできません./clrコードを記述する場合は、新しいスレッドが管理リソースにアクセスする前に正しいアプリケーションドメインに入ることを確認する必要があります.たとえばcall_を使用するとin_appdomain Functionでこの操作を実行します.第2のリロードはアプリケーションドメインが安全である.新しく作成されたスレッドは常に_beginthreadまたは_beginthreadexの呼び出し元のアプリケーションドメインの末尾.

次の例では、_beginthreadと_endthread.
// crt_BEGTHRD.C
// compile with: /MT /D "_X86_" /c
// processor: x86
#include 
#include     /* _beginthread, _endthread */
#include 
#include 
#include 

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

次の例のコードは、同期API WaitForSingleObjectを使用する方法を示しています.beginthreadexが返すスレッドハンドル.プライマリ・スレッドは、続行する前に2番目のスレッドの終了を待機します.2番目のスレッドが呼び出されると_endthreadexの場合、スレッドオブジェクトが信号状態になります.これにより、プライマリ・スレッドが実行を続行できます.使用できませんbeginthreadと_endthreadは、_endthreadはCloseHandleを呼び出し、信号状態に設定できる前にスレッドオブジェクトを破壊します.
// crt_begthrdex.cpp
// compile with: /MT
#include 
#include 
#include 

unsigned Counter;
unsigned __stdcall SecondThreadFunc( void* pArguments )
{
    printf( "In second thread...
"
); while ( Counter < 1000000 ) Counter++; _endthreadex( 0 ); return 0; } int main() { HANDLE hThread; unsigned threadID; printf( "Creating second thread...
"
); // 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
"
, Counter ); // Destroy the thread object. CloseHandle( hThread ); }

参照先_beginthread,_beginthreadex