Sdílet prostřednictvím


_beginthread _beginthreadex vrací

Vytváří vlákno.

Důležitá poznámkaDůležité

Toto rozhraní API nelze použít v aplikacích, které jsou spuštěny v systému Windows Runtime.Další informace naleznete v tématu CRT funkce nejsou podporovány s /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 
);

Parametry

  • start_address
    Počáteční adresa rutiny, která začíná provádění nového vlákna.Pro _beginthread, konvence volání je buď __cdecl (pro nativní kód) nebo __clrcall (pro spravovaný kód); pro _beginthreadex, je __stdcall (pro nativní kód) nebo __clrcall (pro spravovaný kód).

  • stack_size
    Velikost zásobníku pro nové vlákno nebo 0.

  • Arglist
    Seznam argumentů mají být předány do nového vlákna nebo hodnotu NULL.

  • Security
    Ukazatel SECURITY_ATTRIBUTES strukturu, která určuje, zda může vrácený popisovač zděděn podřízenými procesy.Hodnota NULL znamená, které nemůžou být zděděny na úchyt.Musí být aplikace NULL pro systém Windows 95.

  • Initflag
    Počáteční stav nového vlákna (0 pro spuštění nebo CREATE_SUSPENDED pro pozastaveno); použít ResumeThread toto vlákno spustit.

  • Thrdaddr
    Odkazuje na 32bitové proměnné, která přijímá identifikátor podprocesu.Může být NULL, v tom případě není použit.

Vrácená hodnota

Pokud je úspěšná, každá z těchto funkcí vrací popisovač do nově vytvořeného vlákna; však, je-li nově vytvořené vlákno ukončí příliš rychle _beginthread nemusí vrátit platný popisovač (viz popis v Remarks oddílu)._beginthreadv takovém případě vrátí chybu, L-1 errno je nastavena na EAGAIN pokud existuje příliš mnoho podprocesů na EINVAL je-li argument je neplatný nebo není správná velikost zásobníku, nebo na EACCES v případě nedostatku prostředků (například paměti)._beginthreadexv takovém případě vrátí 0 na chybu, errno a _doserrno jsou nastaveny.

Pokud startaddress je NULL, je vyvolána obslužná rutina neplatný parametr, jak je popsáno v Ověření parametrů.Pokud je povoleno zpracování, chcete-li pokračovat, tyto funkce set errno na EINVAL a vrátí hodnotu -1.

Další informace o těchto i jiných návratové kódy, viz _doserrno, kód chyby, _sys_errlist a _sys_nerr.

Další informace o uintptr_t, viz Standardní typy.

Poznámky

_beginthread Funkce vytvoří podproces, který začíná spuštění rutiny na start_address.Rutina na start_address musí používat __cdecl (pro nativní kód) nebo __clrcall (pro spravovaný kód) konvence volání a by měla mít žádné návratové hodnoty.Je-li vlákno přínosu této rutiny, je automaticky ukončeno.Další informace o vláknech, viz Multithreading.

_beginthreadexWin32 se podobá CreateThread rozhraní API více úzce než _beginthread nemá._beginthreadexliší se od _beginthread následujícími způsoby:

  • _beginthreadextři další parametry: initflag, security, a threadaddr.Nové vlákno v pozastaveném stavu, s zadaný zabezpečení (pouze systém Windows NT), lze vytvořit a je přístupný pomocí thrdaddr, což je identifikátor podprocesu.

  • Rutina na start_address byl předán _beginthreadex musí používat __stdcall (pro nativní kód) nebo __clrcall (pro spravovaný kód) konvence volání a musí vracet ukončovací kód vlákna.

  • _beginthreadexna selhání než L-1, vrátí hodnotu 0.

  • Podproces vytvořen s _beginthreadex je ukončena volání _endthreadex.

_beginthreadex Funkce vám dává větší kontrolu nad vytvoření podprocesu než _beginthread nemá._endthreadex Funkce je flexibilnější.Například s _beginthreadex, můžete použít informace o zabezpečení, nastavte počáteční stav podprocesu (spuštěno nebo pozastaveno) a získat identifikátor podprocesu nově vytvořeného vlákna.Je také možné použít popisovač podprocesu, který je vrácený _beginthreadex se synchronizací rozhraní API, které není možné provádět pomocí _beginthread.

Je bezpečnější používat _beginthreadex než _beginthread.Pokud podproces generovaných _beginthread rychle, ukončí popisovač vrácený do volajícího _beginthread může být neplatná, nebo horší, přejděte v jiném vlákně.Však popisovač vrácený _beginthreadex musí se uzavřít volajícím z _beginthreadex, takže je zaručena za platný, pokud _beginthreadex nevrací chybu.

Můžete zavolat _endthread nebo _endthreadex explicitně na ukončení podprocesu. Nicméně _endthread nebo _endthreadex je volána automaticky, když se vlákno vrátí z rutinní předán jako parametr.Ukončení vlákna s voláním endthread nebo _endthreadex pomáhá zajistit správné využívání prostředků přidělených pro vlákno.

_endthreadautomaticky zavře popisovač podprocesu (že _endthreadex neexistuje).Proto při použití _beginthread a _endthread, popisovač podprocesu explicitně nezavírejte voláním rozhraní Win32 CloseHandle rozhraní API.Toto chování se liší od rozhraní Win32 ExitThread rozhraní API.

[!POZNÁMKA]

Pro spustitelný soubor propojený s Libcmt.lib, nevolejte Win32 ExitThread rozhraní API; To zabrání tomu, aby systém run-time uvolní přidělených prostředků._endthreada _endthreadex uvolnit prostředky přidělené vlákna a poté zavolejte ExitThread.

Operační systém zpracovává přidělení zásobníku při obou _beginthread nebo _beginthreadex se nazývá; není třeba předat adresu zásobníku podprocesu kterékoli z těchto funkcí.Kromě toho stack_size argument může být 0, ve kterém operační systém používá stejnou hodnotu jako zásobník, určené pro hlavní podproces.

arglistje parametr předaný do nově vytvořeného vlákna.Obvykle je adresa datové položky, jako je například řetězec znaků.arglistmůže být NULL Pokud není nutné, ale _beginthread a _beginthreadex musí být vybaveny některé hodnoty předat do nového vlákna.Všechny podprocesy jsou ukončena, pokud žádný podproces volání abort, exit, _exit, nebo ExitProcess.

Národní prostředí nové vlákno pochází z jeho nadřazené vlákno.Je-li pro vlákno je povoleno národní prostředí pomocí volání _configthreadlocale (globálně nebo pro nová vlákna), vlákna lze změnit pouze své národní prostředí nezávisle z nadřazeného voláním setlocale nebo _wsetlocale.Další informace naleznete v tématu národního prostředí.

Pro smíšené a čistý kód _beginthread a _beginthreadex mají oba dva přetížení, jeden začíná ukazatele nativní funkce konvence volání, na přijímání __clrcall ukazatel na funkci.První přetížení není bezpečné domény aplikace a nikdy nebude třeba.Pokud vytváříte smíšené nebo čistý kód musí zajistit, nové vlákno před přistupuje spravovaných prostředků přejde do správného používání domény.Toho dosáhnete, například pomocí Funkce call_in_appdomain.Druhý přetížení je aplikační domény bezpečné; do nově vytvořeného vlákna bude vždy skončí v doméně aplikace volající _beginthread nebo _beginthreadex.

Požadavky

Byla zahájena rutina

Požadované záhlaví

_beginthread

<process.h>

_beginthreadex

<process.h>

Další informace o kompatibilitě v tématu Compatibility v úvodu.

Knihovny

Verze s více podprocesy C run-time libraries pouze.

Chcete-li použít _beginthread nebo _beginthreadex, aplikace se musí propojit s jedním s více podprocesy C run-time libraries.

Příklad

Následující příklad používá _beginthread a _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();
}
  Stisknutím libovolné klávesy end

Následující ukázkový kód demonstruje, jak použít popisovač podprocesu, který je vrácený _beginthreadex se synchronizací rozhraní API WaitForSingleObject.Hlavní podproces čeká na druhý podproces ukončit dříve, než pokračuje.Když volá druhý podproces _endthreadex, způsobí, že jeho objekt vlákna přejdete do signalizovaném stavu.To umožňuje primární vlákno, chcete-li pokračovat v práci.Tuto akci nelze provést s _beginthread a _endthread, protože _endthread volání CloseHandle, zničení objektu podproces dříve, než může být nastavena na signalizovaném stavu.

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

Ekvivalent v rozhraní .NET Framework

System::Threading::Thread::Start

Viz také

Referenční dokumentace

Proces a řízení prostředí

_endthread _endthreadex

abort

exit, _exit

GetExitCodeThread