Share via


_beginthread, _beginthreadex

Crée un thread.

Important

Cette API ne peut pas être utilisée dans les applications qui s'exécutent dans les fenêtres d'exécution.Pour plus d'informations, consultez Fonctions CRT non prises en charge avec /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 
);

Paramètres

  • start_address
    Adresse de début d'une routine qui commence l'exécution d'un nouveau thread.Pour _beginthread, la convention d'appel est __cdecl (pour le code natif) ou __clrcall (pour le code managé) ; pour _beginthreadex, c'est __stdcall (pour le code natif) ou __clrcall (pour le code managé).

  • stack_size
    Taille de la pile pour un nouveau thread ou 0.

  • Arglist
    Liste d'arguments à passer à un nouveau thread ou la valeur NULL.

  • Security
    Pointeur vers une structure d' SECURITY_ATTRIBUTES qui détermine si le handle retourné peut être héritée par les processus enfant.Si NULL, le handle ne peut pas être héritée.Doit être NULL pour les applications Windows 95.

  • Initflag
    État initial d'un nouveau thread (0 pour exécuter ou d' CREATE_SUSPENDED pour suspendu) ; utilisation ResumeThread d'exécution du thread.

  • Thrdaddr
    Pointe vers une variable de 32 bits qui accepte l'ID de thread.Peut être NULL, auquel cas il n'est pas utilisé.

Valeur de retour

En cas de réussite, chacune de ces fonctions retourne un handle vers le thread de création récente ; toutefois, si le thread que vous venez de créer s'arrête trop rapidement, _beginthread ne peut pas retourner un handle valide (consultez la discussion dans la section d' Remarks )._beginthread retourne -1L sur une erreur, dans ce cas errno a la valeur EAGAIN s'il y a trop de threads, à EINVAL si l'argument est incorrect ou la taille de la pile est pas valide, ou à EACCES dans le cas de les ressources insuffisantes (telles que la mémoire)._beginthreadex retourne 0 sur une erreur, dans ce cas errno et _doserrno sont définis.

Si startaddress est NULL, le gestionnaire de paramètre non valide est appelé, comme décrit dans Validation des paramètres.Si est autorisé à l'exécution pour continuer, ces errno défini par fonctions à EINVAL et à retourner -1.

Pour plus d'informations sur ces derniers et d'autres codes de retour, consultez l' _doserrno, errno, _sys_errlist, et _sys_nerr.

Pour plus d'informations sur uintptr_t, consultez l' Types standard.

Notes

La fonction d' _beginthread crée un thread qui commence l'exécution d'une routine à start_address.La routine à start_address doit utiliser __cdecl (pour le code natif) ou la convention d'appel d' __clrcall (pour le code managé) et ne doit avoir aucune valeur de retour.Lorsque le thread retourne la valeur de cette routine, il est arrêté automatiquement.Pour plus d'informations sur les threads, consultez l' Fonction multithread.

_beginthreadex ressemble à l'API Win32 CreateThread plus étroitement qu' _beginthread fait._beginthreadex diffère d' _beginthread des façons suivantes :

  • _beginthreadex a trois paramètres supplémentaires : initflag, security, et threadaddr.Le nouveau thread peut être créé dans un état suspendu, avec une sécurité spécifiée (Windows NT uniquement), et est accessible à thrdaddr, qui est l'ID de thread.

  • La routine à start_address est passé à _beginthreadex doit utiliser __stdcall (pour le code natif) ou la convention d'appel d' __clrcall (pour le code managé) et doit retourner un code de sortie du thread.

  • _beginthreadex retourne 0 en cas de échec, plutôt que -1L.

  • Un thread créé avec _beginthreadex est terminé par un appel à _endthreadex.

La fonction d' _beginthreadex vous permet de mieux contrôler la façon dont le thread est créé à _beginthread fait.La fonction d' _endthreadex est également plus flexible.Par exemple, avec _beginthreadex, vous pouvez utiliser les informations de sécurité, définir l'état initial du thread (exécutant ou suspendu), et obtenir l'ID de thread du thread de création récente.Vous pouvez également utiliser le handle du thread retourné par _beginthreadex avec les API de synchronisation, que vous ne pouvez pas faire avec _beginthread.

Il est plus sûr d'utiliser _beginthreadex qu' _beginthread.Si le thread généré par _beginthread se ferme rapidement, le handle retourné à l'appelant d' _beginthread peut être incorrect ou, pire, pointez vers un autre thread.Toutefois, le handle retourné par _beginthreadex doit être fermé par l'appelant d' _beginthreadex, donc il est garanti qu'un handle valide si _beginthreadex ne renvoyait pas une erreur.

Vous pouvez appeler _endthread ou _endthreadex explicitement pour terminer un thread ; toutefois, _endthread ou _endthreadex est appelée automatiquement lorsque le thread retourne de la routine passé comme paramètre.Effectuer un thread avec un appel à endthread ou à _endthreadex aide à garantir une récupération appropriée des ressources allouées pour le thread.

_endthread ferme automatiquement le handle du thread (bien qu' _endthreadex ne fait pas.)Par conséquent, l'utilisation de _beginthread et _endthread, ne fermez pas explicitement le handle du thread en appelant l'API Win32 CloseHandle .Ce comportement diffère de l'API Win32 ExitThread .

[!REMARQUE]

Pour un exécutable lié avec Libcmt.lib, n'appelez pas l'API Win32 ExitThread ; cela empêché le système runtime de libérer les ressources allouées._endthread et la récupération d' _endthreadex allouée thread les ressources puis appelez ExitThread.

Le système d'exploitation gère l'allocation de la pile lorsque _beginthread ou _beginthreadex est appelé ; vous n'avez pas besoin de passer l'adresse de la pile des threads à l'un ou l'autre de ces fonctions.En outre, l'argument d' stack_size peut être 0, auquel cas le système d'exploitation utilise la même valeur que la pile spécifiée pour le thread principal.

arglist est un paramètre à passer au thread de création récente.En général il s'agit de l'adresse d'un élément de données, tel qu'une chaîne.arglist peut être NULL s'il n'est pas nécessaire, mais _beginthread et _beginthreadex doivent être instrumentés d'une valeur à exécuter au nouveau thread.Tous les threads se terminent si un thread appelle abort, exit, _exit, ou ExitProcess.

Les paramètres régionaux du nouveau thread sont hérités de son thread parent.Si chaque thread les paramètres régionaux sont activés par un appel à _configthreadlocale (ou globalement ou pour de nouveaux threads uniquement), le thread peut modifier ses paramètres régionaux indépendamment de son parent en appelant setlocale ou _wsetlocale.Pour plus d'informations, consultez l' Paramètres régionaux.

Pour mixte et code pure, _beginthread et _beginthreadex les deux ont deux surcharges, une acceptant un pointeur fonction native de la convention d'appel, l'autre prenant un pointeur fonction d' __clrcall .La première surcharge n'est pas sécurisée domaine d'application et ne sera jamais.Si vous êtes écrire combiné ou code pure que vous devez vérifier que le nouveau thread entre dans le domaine correct d'application avant d'accéder à des ressources managées.Pour ce faire, par exemple, à l'aide de call_in_appdomain, fonction.La deuxième surcharge est sécurisée domaine d'application ; le thread de création récente exécutera toujours dans le domaine de application de l'appelant d' _beginthread ou d' _beginthreadex.

Configuration requise

Routine

En-tête requis

_beginthread

<process.h>

_beginthreadex

<process.h>

Pour plus d'informations de compatibilité, consultez l' Compatibilité dans l'introduction.

Bibliothèques

Versions multithread d' Bibliothèques runtime C uniquement.

Pour utiliser _beginthread ou _beginthreadex, l'application doit être liée à l'une des bibliothèques multithread runtime C.

Exemple

L'exemple suivant utilise _beginthread et _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();
}
  appuyez sur n'importe quelle touche pour compléter

L'exemple de code suivant montre comment vous pouvez utiliser le handle du thread retourné par _beginthreadex avec l'API WaitForSingleObjectde synchronisation.Le thread principal attend le deuxième thread se termine avant de continuer.Lorsque le deuxième thread appelle _endthreadex, il fait passer son objet thread à l'état signalé.Cela permet au thread principal pour continuer à exécuter.Cela ne peut pas être fait avec _beginthread et _endthread, car _endthread appelle CloseHandle, détruisant l'objet thread avant de pouvoir être défini à l'état signalé.

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

Équivalent .NET Framework

System::Threading::Thread::Start

Voir aussi

Référence

Processus et contrôle ambiance

_endthread, _endthreadex

abort

exit, _exit

GetExitCodeThread