_beginthread-Funktion, _beginthreadex
Erstellt einen Thread.
Wichtig |
---|
Diese API kann nicht in den Anwendungen verwendet werden, die in der Windows Runtime ausführen.Weitere Informationen finden Sie unter CRT-Funktionen unterstützt nicht mit /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 );
Parameter
start_address
Startadresse einer Routine, die Ausführung eines neuen Threads beginnt.Für _beginthread ist die Aufrufkonvention entweder __cdecl (für systemeigenen Code) oder __clrcall (für verwalteten Code); für _beginthreadex ist es entweder __stdcall (für systemeigenen Code) oder __clrcall (für verwalteten Code).stack_size
Stapelgröße für einen neuen Thread oder 0.Arglist
So fügen Sie einem neuen Thread oder eine NULL übergeben werden, Argumentliste.Security
Zeiger auf eine Struktur SECURITY_ATTRIBUTES, die bestimmt, ob das zurückgegebene Handle durch untergeordnete Prozesse geerbt werden kann.Wenn NULL, das Handle nicht geerbt werden kann.Muss für Windows 95-Anwendungen NULL sein.Initflag
Ausgangszustand eines neuen Threads (0 zum Ausführen oder des CREATE_SUSPENDED für angehalten); Verwendung ResumeThread, den Thread auszuführen.Thrdaddr
Zeigt auf eine 32-Bit-Variable, die den Threadbezeichner empfängt.Der NULL möchte, in diesem Fall jedoch nicht verwendet wird.
Rückgabewert
Wenn erfolgreich, gibt jede dieser Funktionen ein Handle für den neu erstellten Thread zurück; Wenn jedoch die neu erstellten Thread möglicherweise zu schnell, _beginthread kein gültiges Handle zurückgäben (finden Sie in den Ausführungen im Abschnitt Remarks )._beginthread gibt -1L auf einem Fehler zurück, in diesem Fall errno zu EAGAIN, wenn es zu viele Threads vorhanden sind, zu EINVAL, wenn das Argument ungültig ist, oder die Stapelgröße falsch ist oder zu EACCES im Fall nicht Ressourcen festgelegt wird (wie Arbeitsspeicher)._beginthreadex gibt 0 für einen Fehler zurück, in diesem Fall errno und _doserrno festgelegt werden.
Wenn startaddressNULL ist, wird der ungültige Parameterhandler aufgerufen, wie in Parametervalidierung beschrieben.Wenn die Ausführung zulässig ist, um fortzufahren, dieses Funktionen festgelegte errno zu EINVAL und zu geben -1.
Weitere Informationen zu diesen und anderen Rückgabecodes, finden Sie unter _doserrno, errno, _sys_errlist und _sys_nerr.
Weitere Informationen zu uintptr_t, finden Sie unter Standardtypen.
Hinweise
Die _beginthread-Funktion erstellt einen Thread, der Ausführung einer Routine bei start_address beginnt.Die Routine bei start_address muss __cdecl (für systemeigenen Code) oder Aufrufkonvention __clrcall verwenden (für verwalteten Code) und sollte keinen Rückgabewert besitzen.Wenn der Thread aus dieser Routine zurückgibt, wird dieser automatisch beendet.Weitere Informationen zu Threads, finden Sie unter Multithreading.
_beginthreadex ähnelt CreateThread Win32 API genauer, als _beginthread ausführt._beginthreadex unterscheidet sich von _beginthread folgendermaßen:
_beginthreadex hat drei zusätzliche Parameter: initflag, security und threadaddr.Auf der neue Thread kann im unterbrochenen Zustand, mit einer angegebenen Sicherheit (nur Windows NT) erstellt und kann mit thrdaddr zugegriffen werden, die der Threadbezeichner ist.
Die Routine bei start_address weitergegebenen zu _beginthreadex muss __stdcall (für systemeigenen Code) oder Aufrufkonvention __clrcall verwenden (für verwalteten Code) und einen Threadexitcode zurückgeben.
_beginthreadex gibt 0 auf Fehler, anstatt -1L zurück.
Ein Thread, der mit _beginthreadex erstellt wird, wird durch einen Aufruf _endthreadex beendet.
Die _beginthreadex-Funktion können Sie besser steuern, wie der Thread erstellt wird, als _beginthread ausführt.Die _endthreadex-Funktion ist auch flexibler.Beispielsweise können Sie mit _beginthreadex, Sicherheitsinformationen verwenden, den Ausgangszustand des Threads festlegen (fortlaufenden oder angehalten), und den Threadbezeichner des neu erstellten Threads abrufen.Sie sind auch, das Threadhandle zu verwenden, das von _beginthreadex mit der Synchronisierung API zurückgegeben wird, die Sie nicht mit _beginthread ausführen können.
Es ist sicherer, _beginthreadex als _beginthread zu verwenden.Wenn der Thread, der durch _beginthread schnell beendet, das Handle zurückgegeben wird dem Aufrufer von _beginthread generiert wird, möglicherweise oder ungültig ist, Ungültiger, zeigen Sie auf einem anderen Thread.muss jedoch das Handle, das durch _beginthreadex zurückgegeben wird, vom Aufrufer von _beginthreadex geschlossen werden, deshalb ist sichergestellt, um ein gültiges Handle zu werden, wenn _beginthreadex keinen Fehler zurückgibt.
Sie können _endthread-Funktion oder _endthreadex explizit aufrufen, um einen Thread zu beenden, wird jedoch _endthread oder _endthreadex automatisch aufgerufen, wenn der Thread aus der Routine zurückgibt, die als Parameter übergeben wird.Das Beenden eines Threads mit einem Aufruf von endthread oder zu _endthreadex hilft, richtige Wiederherstellung von Ressourcen sicherzustellen, die für den Thread zugeordnet werden.
_endthread schließt automatisch das Threadhandle (während _endthreadex nicht bewirkt).Wenn Sie _beginthread und _endthread verwenden, nicht explizit schließen Sie das Threadhandle, indem Sie CloseHandle Win32 APIs aufrufen.Dieses Verhalten unterscheidet sich von ExitThread Win32 APIs.
Hinweis |
---|
Eine ausführbare Datei, die mit Libcmt.lib verknüpft ist, rufen Sie nicht ExitThread Win32 API auf; dieses verhindert das Laufzeitsystem beim Freigeben von zugeordneten Ressourcen._endthread und zugeordnete _endthreadex Rückgewinnung Tabellen Ressourcen und ruft dann ExitThread auf. |
Das Betriebssystem behandelt die Zuordnung des Stapels, wenn entweder _beginthread oder _beginthreadex aufgerufen wird, Sie müssen nicht, um die Adresse des Threadstapels zu einer dieser Funktionen führen.Außerdem kann das stack_size-Argument 0, in diesem Fall das Betriebssystem den gleichen Wert wie der Stapel verwendet, der für den Hauptthread angegeben wird.
arglist ist ein zum neu erstellten Thread zu übergebenden Parameter.In der Regel ist dies die Adresse eines Datenelements, wie eine Zeichenfolge.arglist kann NULL sein, wenn sie nicht benötigt wird, aber _beginthread und _beginthreadex müssen mit einem bestimmten Wert übergeben Sie für den neuen Thread bereitgestellt werden.Alle Threads sind beendete Thread ggf. abort, exit, _exit oder ExitProcess.
Das Gebietsschema des neuen Threads wird von seinem übergeordneten Thread geerbt.Wenn pro Thread wird Gebietsschema durch einen Aufruf _configthreadlocale (entweder global oder nur für neue Threads), kann der Thread sein Gebietsschema von seinem übergeordneten Element unabhängig ändern können, indem setlocale oder _wsetlocale aufruft.Weitere Informationen finden Sie unter Gebietsschema.
Für - und reinen Code haben _beginthread und _beginthreadex beide zwei Überladungen, eine, die einen systemeigenen Aufrufkonventionsfunktionszeiger, die andere akzeptiert, die einen __clrcall-Funktionszeiger akzeptiert.Die erste Überladung ist nicht Anwendung DomäneSAFE und niemals wird sein.Wenn Sie, schreiben oder kombinieren, reiner Code müssen Sie sicherstellen, dass der neue Thread die richtige Anwendungsdomäne eingibt, bevor er auf verwaltete Ressourcen zugreift.Dazu können Sie beispielsweise unter call_in_appdomain-Funktion verwenden.Die zweite Überladung ist Anwendung DomäneSAFE; der neu erstellte Thread beendet immer oben in der Anwendungsdomäne des Aufrufers von _beginthread oder von _beginthreadex.
Anforderungen
Routine |
Erforderlicher Header |
---|---|
_beginthread |
<process.h> |
_beginthreadex |
<process.h> |
Weitere Kompatibilitätsinformation finden Sie unter Kompatibilität in der Einführung.
Bibliotheken
Das Versionen nur C-Laufzeitbibliotheken.
Um _beginthread oder _beginthreadex zu verwenden, muss die Anwendung mit einer Multithreadanwendung der C-Laufzeitbibliotheken verknüpfen.
Beispiel
Im folgenden Beispiel wird _beginthread und _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();
}
Drücken Sie eine beliebige Taste am Ende
Der folgende Beispielcode zeigt, wie Sie das Threadhandle verwenden können, das von _beginthreadex mit der Synchronisierung API WaitForSingleObject zurückgegeben wird.Die Hauptthreadwartung den zweiten Thread zu beenden, vor dem Fortfahren.Wenn der zweite Thread _endthreadex aufruft, wird er Threadobjekt sein, auf den signalisierten Zustand zu wechseln.Dies ermöglicht dem primären Thread, um mit denen.Dies kann nicht mit _beginthread und _endthread durchgeführt werden, da _endthreadCloseHandle aufruft und das Threadobjekt zerstören, bevor es auf den signalisierten Zustand festgelegt werden kann.
// 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-Entsprechung
System::Threading::Thread::Start
Siehe auch
Referenz
Prozess- und Umgebungssteuerelement