_beginthread, _beginthreadex
Cria um thread.
uintptr_t _beginthread(
void( *start_address )( void * ),
unsigned stack_size,
void *arglist
);
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
Parâmetros
start_address
Inicie o endereço de uma rotina que iniciará a execução de uma nova thread.For _beginthread, é a convenção de chamada __cdecl ou __clrcall; para _beginthreadex, ele é __stdcall ou __clrcall.stack_size
dimensionar de pilha para um novo thread ou 0.arglist
Lista de argumentos que devem passar para um novo thread ou nulo.security
Ponteiro para um SECURITY_ATTRIBUTES estrutura que determina se o identificador retornado pode ser herdado pelos processos filhos.Se for nulo, o identificador não pode ser herdado.Deve ser nulo para Windows 95 aplicativos.initflag
Estado inicial de um novo thread (0 para executar ou CREATE_SUSPENDED para suspenso); use ResumeThread para o processo (thread).thrdaddr
Aponta para uma variável de 32 bit que recebe o identificador de thread.Pode ser NULL, caso em que ele não é usado.
Valor de retorno
Se bem-sucedida, cada uma dessas funções retorna um identificador para o segmento recém-criado; no entanto, se o thread recém-criado é encerrado muito rapidamente, _beginthread poderá não retornar um identificador válido (consulte a discussão na Remarks seção). _beginthread Retorna-1 L no erro, caso em que errno é conjunto para EAGAIN Se houver muitos segmentos para EINVAL Se o argumento é inválido ou o dimensionar da pilha for incorreto, ou para EACCES no caso de recursos insuficientes (sistema autônomo memória). _beginthreadex Retorna 0 em um erro, caso em que errno e _doserrno são definidas.
If startaddress é NULL, o manipulador de parâmetro inválido é chamado, conforme descrito em Validação de parâmetro. Se a execução for permitida para continuar, essas funções conjunto errno para EINVAL e retornar -1.
Para obter mais informações sobre esses e outros códigos de retorno, consulte _doserrno, errno, _sys_errlist e _sys_nerr.
Para obter mais informações sobre o uintptr_t, consulte Tipos padrão.
Comentários
The _beginthread função cria um thread que iniciará a execução de uma rotina no start_address. A rotina de start_address use o __cdecl convenção de chamada e não deve ter nenhum valor retornado. Quando o thread retorna dessa rotina, ela é encerrada automaticamente.Para obter mais informações sobre threads, consulte Multithreading.
_beginthreadex semelhante do Win32 CreateThread API mais próxima que _beginthread não. _beginthreadex é diferente de _beginthread das seguintes maneiras:
_beginthreadex tem três parâmetros adicionais: initflag, security, e threadaddr. O novo thread pode ser criado em um estado suspenso, com uma segurança especificado (somente Windows NT) e pode ser acessado usando thrdaddr, que é o identificador de thread.
A rotina de start_address passado para _beginthreadex use o __stdcall convenção de chamada e deve retornar um código de sair de thread.
_beginthreadex Retorna 0 falha, em vez de-1 L.
Um thread criado com _beginthreadex é terminada por uma telefonar para _endthreadex.
The _beginthreadex função lhe dá mais controle sobre como o segmento é criado de _beginthread não. The _endthreadex função também é mais flexível. Por exemplo, com _beginthreadex, você pode usar as informações de segurança, conjunto o estado inicial do segmento (executando ou suspenso) e obter o identificador de thread do thread recém-criado. Você também é capazes de usar o identificador de thread retornado por _beginthreadex com a sincronização de APIs, o que você não pode fazer com _beginthread.
É mais seguro usar _beginthreadex que _beginthread. Se o thread gerado por _beginthread sai rapidamente, o identificador retornado ao chamador de _beginthread pode ser inválido ou pior, aponte para outro thread. No entanto, o identificador retornado por _beginthreadex tem de ser fechado pelo chamador de _beginthreadex, para que ele é garantido que ser um identificador válido se _beginthreadex não retornou um erro.
Você pode telefonar _endthread or _endthreadex explicitamente para terminar um segmento; no entanto, _endthread ou _endthreadex ed telefonar automatitelefonary quando o thread retorna da rotina é passado sistema autônomo um parâmetro. Encerrando um thread com uma telefonar para endthread ou _endthreadex ajuda a garantir a recuperação adequada de recursos alocados para o thread.
_endthread Fecha automaticamente a thread manipular enquanto ( _endthreadex não). Portanto, ao usar _beginthread e _endthread, não fechar explicitamente o identificador de thread chamando do Win32 CloseHandle API.Esse comportamento é diferente do Win32 ExitThread API.
Observação: |
---|
Para um arquivo executável vinculadas com Libcmt.lib , não telefonar Win32 ExitThread API; isso evita que o em time de execução recursos alocados de sistema de recuperação. _endthread e _endthreadex recuperação thread recursos alocada e, em seguida telefonar ExitThread. |
O sistema operacional controla a alocação da pilha quando qualquer um dos _beginthread ou _beginthreadex é chamado; você não precisa passar o endereço da pilha de thread para qualquer dessas funções. Além disso, a stack_size argumento pode ser 0, em que caso o sistema operacional usa o mesmo valor sistema autônomo a pilha especificada para o thread principal.
arglist é um parâmetro a serem passados para o recém-criado thread. Geralmente é o endereço de um item de dados, sistema autônomo uma seqüência de caractere.arglist pode ser NULL Se não for necessária, mas _beginthread e _beginthreadex deve ser fornecido com algum valor para passar para o novo thread. Todos os threads são encerrados se qualquer thread chama abort, exit, _exit, ou ExitProcess.
A localidade do novo thread é herdada do seu segmento pai.Se por thread local estiver habilitado por uma telefonar para _configthreadlocale (globalmente ou para novos threads somente), o thread pode alterar sua localidade independentemente de seu pai chamando setlocale ou _wsetlocale. Para obter mais informações, consulte Localidade.
Para misto e código puro, _beginthread e _beginthreadex ambos têm duas sobrecargas uma demorando um ponteiro de função nativa de convenção de chamada, Outros levando um __clrcall ponteiro de função. A primeira sobrecarga não é segura para domínio do aplicativo e nunca será ser.Se você estiver escrevendo código misto ou puro, você deve garantir que o novo thread entra o domínio do aplicativo correto antes que ele acesse recursos gerenciado.Você pode fazer isso, por exemplo, usando call_in_appdomain da função. A segunda sobrecarga é segura para domínio do aplicativo; o segmento recém-criado sempre acabará no domínio do aplicativo do chamador de _beginthread ou _beginthreadex.
Requisitos
Rotina |
Cabeçalho necessário |
---|---|
_beginthread |
<processo.h> |
_beginthreadex |
<processo.h> |
Para obter mais informações de compatibilidade, consulte Compatibilidade na introdução.
Bibliotecas
Versões multithread do C em time de execução bibliotecas somente.
Para usar _beginthread ou _beginthreadex, o aplicativo deve vincular com uma das bibliotecas do time de execução C multithread.
Exemplo
O exemplo a seguir utiliza _beginthread e _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();
}
press any key to end
Exemplo de código a seguir demonstra como você pode usar o identificador de thread retornado por _beginthreadex com a API de sincronização WaitForSingleObject.O thread principal aguarda o segmento segundo terminar antes de continuar.Quando o segundo thread chama _endthreadex, ela faz com que seu objeto de segmento ir para o estado sinalizado. Isso permite que o thread principal para continuar a executar.Isso não pode ser concluído com _beginthread e _endthread, pois _endthread chamadas CloseHandle, destruir o objeto thread antes que pode ser definida como estado sinalizado.
// 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
Equivalente do NET Framework
sistema::Threading::Thread::Start