Threading di Windows: _beginthreadex vs _beginthreadex vs CreateThread C ++


133

Qual è il modo migliore per iniziare una discussione _beginthread, _beginthreadxoppure CreateThread?

Sto cercando di determinare quali sono i vantaggi / gli svantaggi di _beginthread, _beginthreadexe CreateThread. Tutte queste funzioni restituiscono un handle di thread a un thread appena creato, so già che CreateThread fornisce alcune informazioni aggiuntive quando si verifica un errore (può essere verificato chiamando GetLastError) ... ma quali sono alcune cose che dovrei considerare quando sto usando queste funzioni?

Sto lavorando con un'applicazione Windows, quindi la compatibilità multipiattaforma è già fuori discussione.

Ho esaminato la documentazione di msdn e non riesco proprio a capire, ad esempio, perché qualcuno dovrebbe decidere di usare _beginthread invece di CreateThread o viceversa.

Saluti!

Aggiornamento: OK, grazie per tutte le informazioni, ho anche letto in un paio di posti che non posso chiamare WaitForSingleObject()se lo usassi _beginthread(), ma se chiamo _endthread()nel thread non dovrebbe funzionare? Qual è il problema lì?


2
Ecco un'analisi di ciò che fa _beginthreadex () per i programmatori C / C ++ che ho trovato da un link sul sito Web di Eli Bendersky. Questo è da una domanda e risposta sull'opportunità di utilizzare CreateThread () o meno. microsoft.com/msj/0799/win32/win320799.aspx
Richard Chambers,

Risposte:


96

CreateThread() è una chiamata API Win32 non elaborata per la creazione di un altro thread di controllo a livello di kernel.

_beginthread()e _beginthreadex()sono chiamate di libreria C runtime che chiamano CreateThread()dietro le quinte. Una volta CreateThread()restituito, _beginthread/ex()si occupa della contabilità aggiuntiva per rendere la libreria di runtime C utilizzabile e coerente nel nuovo thread.

In C ++ dovresti quasi certamente usare a _beginthreadex()meno che non ti colleghi alla libreria C runtime (alias MSVCRT * .dll / .lib).


39
Questo non è più vero come una volta. Il CRT funzionerà correttamente in un thread creato da CreateThread () ad eccezione della funzione signal (). Ci sarà una piccola perdita di memoria (~ 80 byte) per ogni thread creato con CreateThread () che utilizza CRT, ma funzionerà correttamente. Per ulteriori informazioni: support.microsoft.com/default.aspx/kb/104641
John Dibling,

1
@John: In realtà quel bug si applica solo fino a MSVC ++ 6.0
bobobobo

5
@bobobobo: buona domanda. Posso solo ipotizzare che MS originariamente intendesse le _beginroutine come chiamate interne e CreateThreaddoveva essere la funzione API che tutti avrebbero chiamato. Un'altra potenziale spiegazione è che la SM ha una storia lunga e gloriosa di ignorare lo standard e prendere decisioni molto sbagliate sulla denominazione delle cose.
John Dibling,

15
Le _beginfunzioni iniziano con un trattino basso perché Microsoft ha iniziato a seguire lo standard più da vicino. Nel runtime C, i nomi che sono con trattino basso sono riservati per l'implementazione (e l'implementazione può documentarli per l'uso dell'utente finale, come con questi). beginthreadex()è un nome che è consentito all'utente. Se il runtime C lo utilizzava, potrebbe essere in conflitto con un simbolo dell'utente finale che l'utente aveva il diritto legittimo di poter prevedere di utilizzare. Si noti che le API Win32 non fanno parte del runtime C e utilizzano lo spazio dei nomi dell'utente.
Michael Burr,

2
@Lothar: ci sono differenze tra la chiamata API Win32 CreateThreade le chiamate CRT _beginthread/exe quando si chiama il CRT su un thread, dovrebbe sempre essere creato con _beginthread/ex. In caso contrario, potrebbero non esserci più perdite di memoria. Ad esempio, sicuramente non verrà inizializzato correttamente l'ambiente in virgola mobile durante la chiamata CreateThread. C'è di più : "Se un thread creato utilizzando CreateThread chiama CRT, il CRT potrebbe terminare il processo in condizioni di memoria insufficiente."
Probabile

37

Esistono diverse differenze tra _beginthread()e _beginthreadex(). _beginthreadex()è stato fatto per agire più come CreateThread()(in entrambi i parametri e come si comporta).

Come accenna Drew Hall , se si utilizza il runtime C / C ++, è necessario utilizzare _beginthread()/ _beginthreadex()anziché in CreateThread()modo che il runtime abbia la possibilità di eseguire la propria inizializzazione del thread (impostazione dell'archiviazione locale dei thread, ecc.).

In pratica, ciò significa che non CreateThread()dovrebbe praticamente mai essere utilizzato direttamente dal tuo codice.

I documenti MSDN per _beginthread()/ _beginthreadex()hanno un po 'di dettagli sulle differenze - uno dei più importanti è che poiché l'handle di thread per un thread creato da _beginthread()viene chiuso automaticamente dal CRT quando il thread esce, "se il thread generato da _beginthread esce rapidamente, l'handle restituito al chiamante di _beginthread potrebbe non essere valido o, peggio ancora, indicare un altro thread ".

Ecco cosa _beginthreadex()dicono i commenti nella fonte CRT:

Differences between _beginthread/_endthread and the "ex" versions:

1)  _beginthreadex takes the 3 extra parameters to CreateThread
  which are lacking in _beginthread():
    A) security descriptor for the new thread
    B) initial thread state (running/asleep)
    C) pointer to return ID of newly created thread

2)  The routine passed to _beginthread() must be __cdecl and has
  no return code, but the routine passed to _beginthreadex()
  must be __stdcall and returns a thread exit code.  _endthread
  likewise takes no parameter and calls ExitThread() with a
  parameter of zero, but _endthreadex() takes a parameter as
  thread exit code.

3)  _endthread implicitly closes the handle to the thread, but
  _endthreadex does not!

4)  _beginthread returns -1 for failure, _beginthreadex returns
  0 for failure (just like CreateThread).

Aggiornamento gennaio 2013:

Il CRT per VS 2012 ha un ulteriore bit di inizializzazione eseguito in _beginthreadex(): se il processo è una "app in pacchetto" (se viene restituito qualcosa di utile GetCurrentPackageId()) il runtime inizializzerà l'MTA sul thread appena creato.


3
Ci sono momenti appropriati in cui CreateThread () è garantito, ma onestamente devi davvero fare di tutto per farlo. Stiamo parlando di una completa mancanza di qualcosa di portatile e scrivendo una DLL o un'API API esclusivamente WIN32. Inclusa nessuna chiamata C-runtime. Anche l'utilizzo di STL è limitato in quanto è necessario fornire allocatori personalizzati per utilizzare le funzioni di gestione della memoria WIN32. L'installazione per fare questo con Developer Studio è di per sé un lavoro, ma per una lib sempre-sempre-WIN32 con il minimo ingombro possibile, può essere fatto. Ma sì, non è dannatamente probabile per quasi tutti, ma pochi molto selezionati.
WhozCraig,

1
@WhozCraig: ci sono limitazioni più gravi quando si omette il CRT. I più importanti sono: nessun supporto per numeri interi a 64 bit, nessun supporto in virgola mobile e, soprattutto, nessuna gestione delle eccezioni. Ciò non significa in realtà alcuna gestione delle eccezioni . Neanche eccezioni SEH. Questo è particolarmente difficile da compensare e le possibilità di chiamare CreateThreadla Cosa Giusta sono sempre più scarse.
Indispensabile il

@MichaelBurr: potresti voler aggiornare la tua risposta per VC ++ 2015 .
user541686,

@Mehrdad: Quali modifiche trovi specificamente degne di nota?
IIprevedibile

Ho scoperto che DisableThreadLibraryCalls non ha alcun effetto sui thread creati con CreateThread, ma disabilita i thread creati con _beginthread o _beginthreadex.
SPlatten,

23

In generale, la cosa giusta da fare è chiamare _beginthread()/_endthread()(o le ex()varianti). Tuttavia, se si utilizza il CRT come .dll, lo stato CRT verrà inizializzato e distrutto correttamente man mano che i CRT DllMainverranno chiamati con DLL_THREAD_ATTACHe DLL_THREAD_DETACHquando si chiama CreateThread()e ExitThread()o si restituisce, rispettivamente.

Il DllMaincodice per CRT può essere trovato nella directory di installazione per VS in VC \ crt \ src \ crtlib.c.


Ottimo punto di partenza Con un po 'di debug si può mostrare che __CRTDLL_INIT viene chiamato anche per un CRT collegato staticamente. Callstack l'init viene chiamato da _LdrpCallInitRoutine @ 16 (), non sono sicuro di quale meccanismo. Ciò significa che con la recente CRT tutta l'inizializzazione / deinizializzazione viene eseguita correttamente ad eccezione della gestione del segnale, che viene comunque eseguita nella funzione di supporto _threadstartex chiamata da beginthread, ma non da CreateThread. Forse potresti aggiungere questo nella risposta e assegnerò la taglia?
Suma,

Premio Bounty, in quanto sembra molto utile. Tuttavia, la risposta potrebbe forse valere la pena di essere aggiornata. Se non riesci a farlo, potrei rivederlo entro pochi giorni.
Suma,

1
@MSN: Tenere presente che CreateThread è ancora danneggiato in una DLL, se si collega nuovamente il CRT statico e si è chiamato DisableThreadLibraryCalls che disabilita le chiamate per DLL_THREAD_DETACH. Quindi otterrai perdite di memoria. Questo è documentato qui nel mio articolo KB: support.microsoft.com/kb/555563/en-us
Jochen Kalmbach,

17

Questo è il codice alla base di _beginthreadex(vedi crt\src\threadex.c):

    /*
     * Create the new thread using the parameters supplied by the caller.
     */
    if ( (thdl = (uintptr_t)
          CreateThread( (LPSECURITY_ATTRIBUTES)security,
                        stacksize,
                        _threadstartex,
                        (LPVOID)ptd,
                        createflag,
                        (LPDWORD)thrdaddr))
         == (uintptr_t)0 )
    {
            err = GetLastError();
            goto error_return;
    }

Il resto _beginthreadexinizializza la struttura dati per thread per CRT.

Il vantaggio dell'utilizzo _beginthread*è che le chiamate CRT dal thread funzioneranno correttamente.


12

Dovresti usare _beginthreado_beginthreadex per consentire alla libreria di runtime C di eseguire la propria inizializzazione del thread. Solo i programmatori C / C ++ devono saperlo come dovrebbero ora le regole di utilizzo del proprio ambiente di sviluppo.

Se lo usi _beginthreadnon è necessario chiamare CloseHandlecome RTL farà per te. Questo è il motivo per cui non puoi aspettare sull'impugnatura se hai usato _beginthread. Anche_beginthread crea confusione se la funzione thread esce immediatamente (rapidamente) poiché il thread di avvio può essere lasciato con un handle di thread non valido sul thread appena avviato.

_beginthreadexgli handle possono essere utilizzati per l'attesa ma richiedono anche una chiamata esplicita a CloseHandle. Questo fa parte di ciò che li rende sicuri per l'uso con wait. Un altro problema per renderlo completamente infallibile è avviare sempre il thread sospeso. Verifica esito positivo, gestione record ecc. Il thread di ripresa. Ciò è necessario per impedire la terminazione di un thread prima che il thread di avvio possa registrarne l'handle.

La migliore pratica è utilizzare _beginthreadex, avviare sospeso quindi riprendere dopo aver registrato l'handle, attendere che l'handle sia OK, CloseHandledeve essere chiamato.


8

CreateThread()usato per avere perdite di memoria quando si utilizzano le funzioni CRT nel codice. _beginthreadex()ha gli stessi parametri CreateThread()ed è più versatile di _beginthread(). Quindi ti consiglio di usare _beginthreadex().


2
Articolo del 1999, da allora potrebbe essere stato risolto
bobobobo il

1
Questo articolo del 2005 conferma ancora che c'è un problema.
Jaywalker,

2
Sì, si applica solo a MSVC ++ 6.0 Service Pack 5 e precedenti. (vedi il menu a discesa "Si applica a" espandibile). Questo non è un problema oggi se si utilizza VC7 o versioni successive.
bobobobo,

1
Questo è ancora un problema, se si collega nuovamente il CRT statico! Inoltre è ancora un problema se si chiama DisableThreadLibraryCalls in una DLL collegata staticamente; vedi il mio articolo KB: support.microsoft.com/kb/555563/en-us
Jochen Kalmbach

2
Hai travisato l'informazione: CreateThreadnon perde mai memoria. È piuttosto il CRT che lo fa, quando viene chiamato da un thread che non è stato inizializzato correttamente.
Indispensabile il

6

Per quanto riguarda la tua domanda aggiornata: "Ho anche letto in un paio di posti che non posso chiamare WaitForSingleObject()se lo avessi usato _beginthread(), ma se chiamo _endthread()nel thread non dovrebbe funzionare?"

In generale, è possibile passare un handle di thread a WaitForSingleObject()(o altre API che attendono su handle di oggetti) per bloccare fino al completamento del thread. Ma l'handle di thread creato da _beginthread()viene chiuso quando _endthread()viene chiamato (che può essere fatto in modo esplicito o implicitamente dal tempo di esecuzione quando ritorna la procedura di thread).

Il problema è segnalato nella documentazione per WaitForSingleObject():

Se questo handle viene chiuso mentre l'attesa è ancora in sospeso, il comportamento della funzione non è definito.


5

Guardando le firme delle funzioni, CreateThreadè quasi identico a _beginthreadex.

_beginthread,_beginthreadx vsCreateThread

HANDLE WINAPI CreateThread(
  __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in       SIZE_T dwStackSize,
  __in       LPTHREAD_START_ROUTINE lpStartAddress,
  __in_opt   LPVOID lpParameter,
  __in       DWORD dwCreationFlags,
  __out_opt  LPDWORD lpThreadId
);

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

Le osservazioni su qui dicono _beginthreadin grado di utilizzare sia __cdeclo __clrcallconvenzione di chiamata come punto di partenza, e _beginthreadexpossono utilizzare __stdcallo__clrcall per il punto di partenza.

Penso che tutti i commenti fatti su perdite di memoria CreateThreadabbiano più di un decennio e che probabilmente dovrebbero essere ignorati.

È interessante notare che entrambe le _beginthread*funzioni chiamano effettivamente CreateThreadsotto il cofano, C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\srcsulla mia macchina.

// From ~line 180 of beginthreadex.c
/*
 * Create the new thread using the parameters supplied by the caller.
 */
if ( (thdl = (uintptr_t)
      CreateThread( (LPSECURITY_ATTRIBUTES)security,
                    stacksize,
                    _threadstartex,
                    (LPVOID)ptd,
                    createflag,
                    (LPDWORD)thrdaddr))
         == (uintptr_t)0 )
{
        err = GetLastError();
        goto error_return;
}

2
Commenta il motivo per cui non dovresti chiamare CreateThread e mescolare le chiamate CRT su quel thread (sicuramente non vecchio di un decennio e sicuramente non dovrebbe essere ignorato) : "Se un thread creato utilizzando CreateThread chiama il CRT, il CRT potrebbe terminare il processo in condizioni di memoria insufficiente. "
Indispensabile il

3

beginthreadexti dà un thread HANDLEper l'uso in WaitForSingleObjecte amici. beginthreadnon lo fa. Non dimenticare di CloseHandle()quando hai finito. La vera risposta sarebbe usare boost::threado presto la classe thread C ++ 09.


La descrizione msdn dice che "Se ha esito positivo, ciascuna di queste funzioni restituisce un handle al thread appena creato;" riferendosi a _beginthread () e _beginthreadex () ...
Kiril,

@Kiril: ma poi la documentazione prosegue dicendo che _beginthread ti chiude la maniglia, il che significa che non puoi usarlo se il thread esce rapidamente ...
Roger Lipscombe,

2

Rispetto a _beginthread, con _beginthreadexè possibile:

  1. Specifica gli attributi di sicurezza.
  2. Avvia un thread in stato sospeso.
  3. È possibile ottenere l'ID thread che può essere utilizzato con OpenThread.
  4. L'handle di thread restituito è garantito per essere valido se la chiamata ha avuto esito positivo. Per te è necessario chiudere la maniglia conCloseHandle .
  5. L'handle di thread restituito può essere utilizzato con le API di sincronizzazione.

Il _beginthreadexstrettamente assomiglia CreateThread, ma il primo è un'implementazione CRT e la seconda una chiamata API di Windows. La documentazione per CreateThread contiene le seguenti raccomandazioni:

Un thread in un eseguibile che chiama la libreria runtime C (CRT) dovrebbe usare le funzioni _beginthreadexe _endthreadexper la gestione dei thread anziché CreateThreade ExitThread; questo richiede l'uso della versione multi-thread del CRT. Se un thread creato utilizzando CreateThreadchiama il CRT, il CRT può terminare il processo in condizioni di memoria insufficiente.


Secondo le specifiche API, i punti 3-5 non sono univoci per _beginthreadex. È possibile eseguire il cast del uintptr_tritorno da entrambe le funzioni a HANDLE.
Andon M. Coleman,

Sì, hai ragione in teoria. In pratica, la differenza è che _beginthreadchiude la maniglia all'uscita. Quindi non è possibile utilizzare in modo affidabile l'handle con le API di sincronizzazione o ottenere l'ID thread fino a quando non si utilizza un altro modo per sincronizzare e duplicare l'handle. Ma poi lo sta _beginthreadexfacendo per te.
Vishal,

2

CreateThread()una volta era un no-no perché il CRT sarebbe stato inizializzato / ripulito in modo errato. Ma questa è ora storia: ora è possibile (utilizzando VS2010 e probabilmente alcune versioni precedenti) chiamare CreateThread()senza interrompere il CRT.

Ecco la conferma ufficiale MS . Si afferma un'eccezione:

In realtà, l'unica funzione che non dovrebbe essere utilizzata in un thread creato con CreateThread()è la signal()funzione.

Tuttavia, dal punto di vista della coerenza, personalmente preferisco continuare a utilizzarlo _beginthreadex().


Mentre suppongo che ciò sia vero, puoi fornire alcune prove autorevoli - collegandoti alla Documentazione MS o analizzando le fonti CRT _beginthreadex / _endthreadex?
Suma,

@Suma, immagino di aver aggiunto il link MS mentre scrivevi il tuo commento ;-)
Serge Wautier,

Il documento a cui si sta collegando non sembra confermare: "Tuttavia, a seconda delle funzioni CRT chiamate, al termine dei thread potrebbe esserci una piccola perdita di memoria". Ciò significa che non è più un no-no grande e generale, ma comunque un no-no se si creano frequentemente thread e si utilizzano quelle funzioni. Tuttavia, il documento è del 2005 e pertanto non può affrontare il recente stato della questione.
Suma,

1
Hmm ... anche se potrebbe dipendere dal caso d'uso, una funzione che lascia una perdita di memoria, indipendentemente dalle dimensioni, considererei un no-no ... - in particolare se esiste un'alternativa senza perdite!
alk

"Ora è possibile chiamare CreateThread () senza interrompere il CRT." - Sfortunatamente, questo non è vero e non lo è mai stato. Da CreateThread : "Un thread in un eseguibile che chiama la libreria runtime C (CRT) dovrebbe utilizzare le funzioni _beginthreadex e _endthreadex per la gestione dei thread [...] Se un thread creato utilizzando CreateThread chiama il CRT, il CRT può terminare il processo in condizioni di memoria insufficiente. "
IIprevedibile

2

CreateThread()è una chiamata API di Windows che è indipendente dalla lingua. Crea solo oggetto OS - thread e restituisce HANDLE a questo thread. Tutte le applicazioni Windows utilizzano questa chiamata per creare thread. Tutte le lingue evitano la chiamata diretta all'API per ovvi motivi: 1. Non vuoi che il tuo codice sia specifico del sistema operativo 2. Devi fare un po 'di manutenzione prima di chiamare in stile API: convertire parametri e risultati, allocare spazio temporaneo ecc.

_beginthreadex()è un wrapper C CreateThread()che rappresenta C specifico. Consente di lavorare con f-n originali a thread singolo in un ambiente multithread allocando l'archiviazione specifica per thread.

Se non usi CRT non puoi evitare una chiamata diretta a CreateThread(). Se si utilizza CRT, è necessario utilizzare _beginthreadex()o alcune stringhe CRT f-n potrebbero non funzionare correttamente prima del VC2005.


1

CreateThread()è la chiamata di sistema diretta. È implementato su Kernel32.dllcui, molto probabilmente, l'applicazione sarà già collegata per altri motivi. È sempre disponibile nei moderni sistemi Windows.

_beginthread()e _beginthreadex()sono funzioni wrapper in Microsoft C Runtime ( msvcrt.dll). Le differenze tra le due chiamate sono riportate nella documentazione. È quindi disponibile quando è disponibile Microsoft C Runtime o se l'applicazione è collegata staticamente contro di essa. Probabilmente ti collegherai anche a quella libreria, a meno che tu non stia codificando in pura API di Windows (come spesso faccio personalmente).

La tua domanda è coerente e in realtà ricorrente. Come molte API, ci sono funzionalità duplicate e ambigue nell'API di Windows che dobbiamo affrontare. Peggio ancora, la documentazione non chiarisce il problema. Suppongo che la _beginthread()famiglia di funzioni sia stata creata per una migliore integrazione con altre funzionalità C standard, come la manipolazione di errno. _beginthread()si integra quindi meglio con il runtime C.

Nonostante ciò, a meno che tu non abbia buoni motivi per usare _beginthread()o _beginthreadex(), dovresti usarlo CreateThread(), principalmente perché potresti avere una dipendenza in libreria in meno nel tuo eseguibile finale (e per MS CRT questo conta un po '). Inoltre, non è presente alcun codice a capo attorno alla chiamata, sebbene questo effetto sia trascurabile. In altre parole, credo che il motivo principale per cui attenersi CreateThread()sia che non esiste un buon motivo _beginthreadex()per cominciare. Le funzionalità sono esattamente o quasi le stesse.

Un buon motivo per usare _beginthread() sarebbe (come sembra essere falso) che gli oggetti C ++ sarebbero opportunamente srotolati / distrutti se _endthread()chiamati.


Non ci sono chiamate di funzioni ambigue affatto . CreateThreadè la chiamata API di Windows per creare un thread. Se si utilizza CRT (poiché si sta programmando in C o C ++), è necessario creare thread utilizzando le _beginthread[ex]chiamate del CRT (che chiamano CreateThreadoltre a eseguire l'inizializzazione CRT necessaria). La differenza più importante tra _beginthreade l'ex-variante: la prima mantiene la proprietà dell'handle di thread nativo, mentre la seconda passa la proprietà al chiamante.
Indispensabile il

Nitpick: nonmsvcrt.dll è la DLL di runtime C! Vedi blogs.msdn.microsoft.com/oldnewthing/20140411-00/?p=1273
Govind Parmar,

0

Le altre risposte non riescono a discutere le implicazioni della chiamata di una funzione di runtime C che avvolge una funzione API Win32. Ciò è importante quando si considera il comportamento di blocco del caricatore DLL.

Indipendentemente dal fatto _beginthread{ex}che sia presente una gestione di thread / thread di memoria C Runtime speciale come discusso dalle altre risposte, è implementato in (assumendo il collegamento dinamico al runtime C) in una DLL che i processi potrebbero non essere ancora stati caricati.

Non è sicuro chiamare _beginthread*da DllMain. Ho provato questo scrivendo una DLL caricata utilizzando la funzionalità "AppInit_DLLs" di Windows. La chiamata _beginthreadex (...)anziché CreateThread (...)fa in modo che MOLTE parti importanti di Windows smettano di funzionare durante l'avvio poiché i DllMaindeadlock del punto di ingresso in attesa del rilascio del blocco caricatore per eseguire determinate attività di inizializzazione.

Per inciso, questo è anche il motivo per cui kernel32.dll ha molte funzioni stringa sovrapposte che anche il runtime C fa - usare quelle da DllMainper evitare lo stesso tipo di situazione.


0

Se leggi il libro Debugging di Windows Application Da Jeffrey Richter, spiega che in quasi tutti i casi devi chiamare _beginthreadexinvece di chiamare CreateThread. _beginthreadè solo un wrapper semplificato in giro _beginthreadex.

_beginthreadexinizializza alcuni interni CRT (C RunTime) che l' CreateThreadAPI non farebbe.

Una conseguenza se si utilizza l' CreateThreadAPI anziché utilizzare le _begingthreadexchiamate alle funzioni CRT potrebbe causare problemi imprevisti.

Dai un'occhiata a questo vecchio Microsoft Journal da Richter.


-2

Non c'è più differenza tra i due.

Tutti i commenti su perdite di memoria ecc. Si basano su versioni <VS2005 molto vecchie. Ho fatto alcuni test di stress anni fa e ho potuto smontare questo mito. Perfino Microsoft mescola gli stili nei loro esempi, quasi mai usando _beginthread.


CreateThread : "Se un thread creato utilizzando CreateThread chiama CRT, il CRT può interrompere il processo in condizioni di memoria insufficiente."
Indispensabile il

Sulla base della sussistenza "richiede l'uso della versione multithread del CRT" presumo che si tratti di immondizia della documentazione in quanto non esiste più una versione crt multithread e da molti anni ormai.
Lothar,

"non esiste più una versione crt multithread" - MSDN afferma che "[t] il CRT a thread singolo non è più disponibile." Non puoi avere entrambi ragione. Vado anche con MSDN qui.
II

Era un errore di battitura, ovviamente intendevo dire che il thread singolo è sparito e il multithread è diventato lo standard e ciò che è andato è la distinzione tra usare o non usare i thread.
Lothar,

Questo sta diventando davvero strano. Ora stai usando un'istruzione, che è senza dubbio corretta ( "richiede l'uso della versione multithread del CRT" ) per affermare che sia questa affermazione che il resto della documentazione sono molto probabilmente sbagliati? Questo sicuramente non suona bene.
IIpersettibile il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.