_beginthread
, _beginthreadex
bir iş parçacığı oluşturur.
Sözdizimi
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
);
Parametreler
start_address
Yeni bir iş parçacığının yürütülmesine başlayan yordamın başlangıç adresi. için_beginthread
, çağırma kuralı (yerel kod için) veya __clrcall
(yönetilen kod için) şeklindedir __cdecl
. için_beginthreadex
, çağırma kuralı (yerel kod için) veya __clrcall
(yönetilen kod için) şeklindedir __stdcall
.
stack_size
Yeni bir iş parçacığı için yığın boyutu veya 0.
arglist
Yeni bir iş parçacığına geçirilecek bağımsız değişken listesi veya NULL
.
Security
Döndürülen tanıtıcının alt işlemler tarafından devralınıp devralınamayacağını belirleyen bir SECURITY_ATTRIBUTES
yapı işaretçisi. ise Security
NULL
, tanıtıcı devralınamaz.
initflag
Yeni iş parçacığının ilk durumunu denetleen bayraklar. Hemen çalıştırılacak veya askıya alınmış durumda iş parçacığı oluşturmak için CREATE_SUSPENDED
0 olarak ayarlayıninitflag
; iş parçacığını yürütmek için kullanınResumeThread
. STACK_SIZE_PARAM_IS_A_RESERVATION
Bayt cinsinden yığının ilk yedek boyutu olarak kullanılacak stack_size
şekilde bayrak olarak ayarlayıninitflag
; bu bayrak belirtilmezse, stack_size
işleme boyutunu belirtir.
thrdaddr
İş parçacığı tanımlayıcısını alan 32 bitlik bir değişkene işaret eder. NULL
ise kullanılmaz.
Dönüş değeri
Başarılı olursa, bu işlevlerin her biri yeni oluşturulan iş parçacığına bir tanıtıcı döndürür; ancak, yeni oluşturulan iş parçacığı çok hızlı _beginthread
çıkar, geçerli bir tanıtıcı döndürmeyebilir. (Açıklamalar bölümündeki tartışmaya bakın.) Bir hatada _beginthread
-1L döndürür ve errno
çok fazla iş parçacığı varsa, EINVAL
bağımsız değişken geçersizse veya yığın boyutu yanlışsa veya EACCES
yetersiz kaynak (bellek gibi) varsa olarak ayarlanırEAGAIN
. Bir hatada _beginthreadex
0 döndürür ve errno
_doserrno
ayarlanır.
ise start_address
NULL
, parametre doğrulamasında açıklandığı gibi geçersiz parametre işleyicisi çağrılır. Yürütmenin devam etmesi için izin verilirse, bu işlevler olarak EINVAL
ayarlanır errno
ve -1 döndürür.
Bunlar ve diğer iade kodları hakkında daha fazla bilgi için bkz. errno
, _doserrno
, _sys_errlist
ve _sys_nerr
.
hakkında uintptr_t
daha fazla bilgi için bkz . Standart türler.
Açıklamalar
işlevi, _beginthread
konumunda start_address
bir yordamın yürütülmesine başlayan bir iş parçacığı oluşturur. yordamının start_address
(yerel kod için) veya __clrcall
(yönetilen kod için) çağırma kuralını kullanması __cdecl
ve dönüş değeri olmaması gerekir. İş parçacığı bu yordamdan geri döndüğünde otomatik olarak sonlandırılır. İş parçacıkları hakkında daha fazla bilgi için bkz . Eski kod için çoklu iş parçacığı desteği (Visual C++).
_beginthreadex
Win32 CreateThread
API'sini olduğundan daha yakından _beginthread
gösterir. _beginthreadex
aşağıdaki şekillerden _beginthread
farklıdır:
_beginthreadex
üç parametresi daha vardır:initflag
,Security
vethreadaddr
. Yeni iş parçacığı, belirtilen bir güvenlikle askıya alınmış durumda oluşturulabilir ve iş parçacığı tanımlayıcısı olan kullanılarakthrdaddr
erişilebilir.geçirilen yordamının
start_address
_beginthreadex
(yerel kod için) veya__clrcall
(yönetilen kod için) çağırma kuralını kullanması__stdcall
ve bir iş parçacığı çıkış kodu döndürmesi gerekir._beginthreadex
-1L yerine hata durumunda 0 döndürür.kullanılarak
_beginthreadex
oluşturulan bir iş parçacığı çağrısı_endthreadex
tarafından sonlandırılır.
işlevi, _beginthreadex
iş parçacığının nasıl oluşturulduğu üzerinde daha fazla _beginthread
denetim sağlar. İşlev _endthreadex
de daha esnektir. Örneğin, ile _beginthreadex
güvenlik bilgilerini kullanabilir, iş parçacığının ilk durumunu ayarlayabilir (çalışıyor veya askıya alındı) ve yeni oluşturulan iş parçacığının iş parçacığı tanımlayıcısını alabilirsiniz. tarafından döndürülen _beginthreadex
iş parçacığı tutamacını eşitleme API'leriyle de kullanabilirsiniz. Bunu ile _beginthread
yapamazsınız.
_beginthreadex
kullanmak yerine daha _beginthread
güvenlidir. tarafından _beginthread
oluşturulan iş parçacığı hızlı bir şekilde çıkar, çağıran _beginthread
için döndürülen tanıtıcı geçersiz veya başka bir iş parçacığı işaret olabilir. Ancak tarafından döndürülen _beginthreadex
tanıtıcının çağıran _beginthreadex
tarafından kapatılması gerekir, bu nedenle hata döndürmediyse geçerli bir tanıtıcı _beginthreadex
olması garanti edilir.
İş parçacığını sonlandırmak için çağırabilir veya _endthreadex
açıkça çağırabilirsiniz_endthread
; ancak iş _endthread
_endthreadex
parçacığı parametre olarak geçirilen yordamdan döndürdüğünde otomatik olarak çağrılır. veya çağrısıyla bir iş parçacığını sonlandırmak _endthread
_endthreadex
, iş parçacığı için ayrılan kaynakların doğru kurtarılmasını sağlamaya yardımcı olur.
_endthread
iş parçacığı tutamacını otomatik olarak kapatır ancak _endthreadex
kapatmaz. Bu nedenle ve _endthread
kullanırken _beginthread
Win32 CloseHandle
API'sini çağırarak iş parçacığı tutamacını açıkça kapatmayın. Bu davranış Win32 ExitThread
API'sinden farklıdır.
Not
Libcmt.lib ile bağlantılı yürütülebilir bir dosya için Win32 ExitThread
API'sini çağırmayın, böylece çalışma zamanı sisteminin ayrılan kaynakları geri almasını engellemeyin. _endthread
ve _endthreadex
ayrılmış iş parçacığı kaynaklarını geri kazanıp çağrısı yapın ExitThread
.
İşletim sistemi ya da _beginthread
_beginthreadex
çağrıldığında yığının ayırmasını işler; iş parçacığı yığınının adresini bu işlevlerden herhangi birine geçirmeniz gerekmez. Buna ek olarak, stack_size
bağımsız değişken 0 olabilir ve bu durumda işletim sistemi ana iş parçacığı için belirtilen yığınla aynı değeri kullanır.
arglist
, yeni oluşturulan iş parçacığına geçirilecek bir parametredir. Genellikle, karakter dizesi gibi bir veri öğesinin adresidir. arglist
gerekli değilse olabilir NULL
, ancak _beginthread
_beginthreadex
yeni iş parçacığına geçirmek için bir değer verilmelidir. herhangi bir iş parçacığı çağrısı abort
, , exit
_exit
veya ExitProcess
ise tüm iş parçacıkları sonlandırılır.
Yeni iş parçacığının yerel ayarı, işlem başına genel geçerli yerel ayar bilgileri kullanılarak başlatılır. İş parçacığı başına yerel ayar çağrısıyla _configthreadlocale
etkinleştirilirse (genel olarak veya yalnızca yeni iş parçacıkları için), iş parçacığı veya _wsetlocale
çağrısı setlocale
yaparak diğer iş parçacıklarından bağımsız olarak yerel ayarını değiştirebilir. İş parçacığı başına yerel ayar bayrağı ayarlı olmayan iş parçacıkları, iş parçacığı başına yerel ayar bayrağı ayarlı olmayan diğer tüm iş parçacıklarında ve ayrıca yeni oluşturulan tüm iş parçacıklarında yerel ayar bilgilerini etkileyebilir. Daha fazla bilgi için bkz . Yerel Ayar.
Kod _beginthread
için /clr
ve _beginthreadex
her birinin iki aşırı yüklemesi vardır. Biri yerel bir çağırma kuralı işlev işaretçisini, diğeri ise işlev __clrcall
işaretçisini alır. İlk aşırı yükleme uygulama etki alanı açısından güvenli değildir ve hiçbir zaman olmayacaktır. Kod yazıyorsanız /clr
, yönetilen kaynaklara erişmeden önce yeni iş parçacığının doğru uygulama etki alanına girdiğinden emin olmanız gerekir. Örneğin, kullanarak call_in_appdomain
bunu yapabilirsiniz. İkinci aşırı yükleme, uygulama etki alanı açısından güvenlidir; yeni oluşturulan iş parçacığı her zaman veya _beginthreadex
öğesini çağıranın _beginthread
uygulama etki alanında olur.
Varsayılan olarak, bu işlevin genel durumunun kapsamı uygulama olarak belirlenmiştir. Bu davranışı değiştirmek için bkz. CRT'de Genel durum.
Gereksinimler
Yordam | Gerekli başlık |
---|---|
_beginthread |
<process.h> |
_beginthreadex |
<process.h> |
Daha fazla uyumluluk bilgisi için bkz . Uyumluluk.
Kitaplıklar
Yalnızca C çalışma zamanı kitaplıklarının çok iş parçacıklı sürümleri.
veya _beginthreadex
kullanmak _beginthread
için uygulamanın çok iş parçacıklı C çalışma zamanı kitaplıklarından biriyle bağlantısı olmalıdır.
Örnekler
Aşağıdaki örnekte ve _endthread
kullanılır_beginthread
.
// 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 * );
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 = ¶m;
// 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, ®ion);
// 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();
}
Örnek uygulamayı sonlandırmak için herhangi bir tuşa basın.
Aşağıdaki örnek kod, tarafından _beginthreadex
döndürülen iş parçacığı tanıtıcısını eşitleme API'siyle WaitForSingleObject
nasıl kullanabileceğinizi gösterir. Ana iş parçacığı, devam etmeden önce ikinci iş parçacığının sonlandırılabilmesini bekler. İkinci iş parçacığı çağırdığında _endthreadex
, iş parçacığı nesnesinin sinyal verilen duruma gitmesine neden olur ve bu da birincil iş parçacığının çalışmaya devam etmesini sağlar. ve ile _beginthread
_endthread
yapılamaz, çünkü _endthread
CloseHandle
çağrıları, iş parçacığı nesnesini sinyalli duruma ayarlanmadan önce yok eder.
// 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