Aracılığıyla paylaş


_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 SecurityNULL, 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. NULLise 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_addressNULL, 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_errlistve _sys_nerr.

hakkında uintptr_tdaha fazla bilgi için bkz . Standart türler.

Açıklamalar

işlevi, _beginthread konumunda start_addressbir 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, Securityve threadaddr. 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ılarak thrdaddreriş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ı _endthreadextarafı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 _beginthreadexgü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 _beginthreadyapamazsınız.

_beginthreadex kullanmak yerine daha _beginthreadgü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 _beginthreadextarafı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 _endthreadkullanı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.

Dekont

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_exitveya ExitProcessise 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_appdomainbunu 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 _beginthreadexkullanmak _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 _endthreadkullanı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 = &param;

    // 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, &region);

        // 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 WaitForSingleObjectnası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_endthreadyapılamaz, çünkü _endthreadCloseHandleç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

Ayrıca bkz.