_beginthreadex

From RAD Studio
Jump to: navigation, search

Go Up to process.h Index


Header File

process.h

Category

Process Control Routines

Prototype

unsigned long _beginthreadex(void *__security_attr, unsigned __stksize, unsigned (__stdcall *__start)(void *), void *__arg, unsigned __create_flags, unsigned *__thread_id);

Description

Creates a thread and allows specifying the other parameters of the OS API CreateThread (such as security and thread creation flags). The _endthreadex function will be called automatically when the thread function terminates. The value returned from your thread function will be passed along to _endthreadex, which in turn will pass it along to the ExitThread API. The return value can then be retrieved using the GetExitCodeThread API.

Unlike _endthread, the _endthreadex function does not close the thread handle, thereby allowing other threads to block on this one without fear that the handle will be freed out from under the system.

Other than the order of parameters and the closing of the thread handle, _beginthreadex performs same operation as _beginthreadNT.

Note: Note: The start address needs to be defined to return an unsigned, which is the thread exit code.

Return Value

_beginthreadex returns the handle of the new thread. The return value is a standard Windows handle that can be used in operating system API's such as SuspendThread and ResumeThread.

If unsuccessful, 0 is returned, and errno is set as follows:

EAGAIN

Too many threads

ENOMEM

Not enough memory

EINVAL

Bad stack value (i.e. less than 16 bytes or equal to zero)



Also see the description of the Win32 API GetLastError, in the MSDN Library.

Example

//*  Use the -tWM  (32-bit multi-threaded target) command-line switch for this example  */
#pragma checkoption -tWM
#include        <windows.h>
#include        <process.h>
#include        <stdio.h>
#define NTHREADS 25
/* This function acts as the 'main' function for each new thread */
static unsigned __stdcall threadMain(void *arg)
{
   printf("Thread %2d has an ID of %u\n", (int)arg, GetCurrentThreadId());
   return 0;
}
int main(void)
{
   HANDLE hThreads[NTHREADS];
   int i;
   unsigned threadId;
   SECURITY_ATTRIBUTES  sa = {
          sizeof(SECURITY_ATTRIBUTES), /* structure size */
          0,      /* No security descriptor */
          TRUE    /* Thread handle is inheritable */
   };
   /* Create NTHREADS inheritable threads that are initially suspended and that will run starting at threadMain()*/
   for(i = 0; i < NTHREADS; i++) {
      hThreads[i] = (HANDLE)_beginthreadex(
         &sa,          /* Thread security */
         4096,         /* Thread stack size */
         threadMain,   /* Thread starting address */
         (void *)i,    /* Thread start argument */
         CREATE_SUSPENDED,  /* Create in suspended state */
         &threadId);   /* Thread ID */
      if(hThreads[i] == INVALID_HANDLE_VALUE) {
         MessageBox(0, "Thread Creation Failed", "Error", MB_OK);
         return  1;
      }
      printf("Created thread %2d with an ID of %u\n", i, threadId);
   }
   printf("\nPress ENTER to thaw all threads\n\n");
   getchar();

/* Resume the suspended threads */
   for(i = 0; i < NTHREADS; i++)
      ResumeThread(hThreads[i]);

/* Wait for the threads to run */
   WaitForMultipleObjects(NTHREADS, hThreads, TRUE, INFINITE);
/* Close all of the thread handles */
   for(i = 0; i < NTHREADS; i++)
      CloseHandle(hThreads[i]);
   return 0;
}

Portability

POSIX Win32 ANSI C ANSI C++

+