CreateThread

The CreateThread function creates a thread to execute within the address space of the calling process.
HANDLE CreateThread(
    LPSECURITY_ATTRIBUTES lpThreadAttributes,   // pointer to thread security attributes  
    DWORD dwStackSize,                          // initial thread stack size, in bytes 
    LPTHREAD_START_ROUTINE lpStartAddress,      // pointer to thread function 
    LPVOID lpParameter,                         // argument for new thread 
    DWORD dwCreationFlags,                      // creation flags 
    LPDWORD lpThreadId                          // pointer to returned thread identifier 
);	

Parameters:

Return Values
If the function succeeds, the return value is a handle to the new thread.
If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Remarks
The new thread handle is created with full access to the new thread. If a security descriptor is not provided, the handle can be used in any function that requires a thread object handle. When a security descriptor is provided, an access check is performed on all subsequent uses of the handle before access is granted. If the access check denies access, the requesting process cannot use the handle to gain access to the thread.
The thread execution begins at the function specified by the lpStartAddress parameter. If this function returns, the DWORD return value is used to terminate the thread in an implicit call to the ExitThread function. Use the GetExitCodeThread function to get the thread's return value.

The CreateThread function may succeed even if lpStartAddress points to data, code, or is not accessible. If the start address is invalid when the thread runs, an exception occurs, and the thread terminates. Thread termination due to a invalid start address is handled as an error exit for the thread's process. This behavior is similar to the asynchronous nature of CreateProcess, where the process is created even if it refers to invalid or missing dynamic-link libraries (DLLs).

The thread is created with a thread priority of THREAD_PRIORITY_NORMAL. Use the GetThreadPriority and SetThreadPriority functions to get and set the priority value of a thread.
When a thread terminates, the thread object attains a signaled state, satisfying any threads that were waiting on the object.
The thread object remains in the system until the thread has terminated and all handles to it have been closed through a call to CloseHandle.

Example:

DWORD parallel_process(LPVOID param)
{
   ...
   return 0;
}

void main()
{
   HANDLE thr_hndl;
   DWORD  thr_id;

   thr_hndl = CreateThread( NULL,
                            THRSTACKSIZE,
                            (LPTHREAD_START_ROUTINE)parallel_process,
                            NULL,
                            0,
                            &thr_id
   );
   ...
   if( thr_hndl == INVALID_HANDLE_VALUE ){
      cerr<<"Error: cannot create thread\n";
      return;
   }
}
You can find a complete example here.

TerminateThread

The TerminateThread function terminates a thread.
BOOL TerminateThread(
    HANDLE hThread,    // handle to the thread 
    DWORD dwExitCode   // exit code for the thread 
);	

Parameters

Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.

Remarks
TerminateThread is used to cause a thread to exit. When this occurs, the target thread has no chance to execute any user-mode code and its initial stack is not deallocated. DLLs attached to the thread are not notified that the thread is terminating.
TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:

Example:

   thr_hndl = CreateThread( NULL,
                            THRSTACKSIZE,
                            (LPTHREAD_START_ROUTINE)parallel_process,
                            NULL,
                            0,
                            &thr_id
   );
   ...
   if( thr_hndl != INVALID_HANDLE_VALUE ) 
      TerminateThread(thr_hndl, 0);

SuspendThread

The SuspendThread function suspends the specified thread.
DWORD SuspendThread(
    HANDLE hThread 	// handle to the thread 
);	

Parameters

Return Values
If the function succeeds, the return value is the thread's previous suspend count; otherwise, it is 0xFFFFFFFF. To get extended error information, use the GetLastError function.

Remarks
If the function succeeds, execution of the specified thread is suspended and the thread's suspend count is incremented.
Suspending a thread causes the thread to stop executing user-mode (application) code.
Each thread has a suspend count (with a maximum value of MAXIMUM_SUSPEND_COUNT). If the suspend count is greater than zero, the thread is suspended; otherwise, the thread is not suspended and is eligible for execution. Calling SuspendThread causes the target thread's suspend count to be incremented. Attempting to increment past the maximum suspend count causes an error without incrementing the count.

The ResumeThread function decrements the suspend count of a suspended thread.

ResumeThread

The ResumeThread function decrements a thread's suspend count. When the suspend count is decremented to zero, the execution of the thread is resumed.
DWORD ResumeThread(
    HANDLE hThread 	// identifies thread to restart 
);	

Parameters

Return Values
If the function succeeds, the return value is the thread's previous suspend count.
If the function fails, the return value is 0xFFFFFFFF. To get extended error information, call GetLastError.

Remarks
The ResumeThread function checks the suspend count of the subject thread. If the suspend count is 0, the thread is not currently suspended. Otherwise, the subject thread's suspend count is decremented. If the resulting value is 0, then the execution of the subject thread is resumed.
If the return value is 0, the specified thread was not suspended. If the return value is 1, the specified thread was suspended but was restarted. If the return value is greater than 1, the specified thread is still suspended.

Note that while reporting debug events, all threads within the reporting process are frozen. Debuggers are expected to use the SuspendThread and ResumeThread functions to limit the set of threads that can execute within a process. By suspending all threads in a process except for the one reporting a debug event, it is possible to "single step" a single thread. The other threads are not released by a continue operation if they are suspended.

Example:

   thr_hndl = CreateThread( NULL,
                            THRSTACKSIZE,
                            (LPTHREAD_START_ROUTINE)parallel_process,
                            NULL,
                            0,
                            &thr_id
   );
   ...
   if( thr_hndl != INVALID_HANDLE_VALUE ){ 
      SuspendThread(thr_hndl);
      cout<<"Main prog: Thread is suspended\n";
      sleep(4);
      ResumeThread(thr_hndl);
   }

WaitForSingleObject

The WaitForSingleObject function returns when one of the following occurs:
  • The specified object is in the signaled state.
  • The time-out interval elapses.
    DWORD WaitForSingleObject(
        HANDLE hHandle,       // handle of object to wait for 
        DWORD dwMilliseconds  // time-out interval in milliseconds  
    );	
    

    Parameters

    Return Values
    If the function succeeds, the return value indicates the event that caused the function to return.
    If the function fails, the return value is WAIT_FAILED. To get extended error information, call GetLastError.
    The return value on success is one of the following values:
    Value Meaning
    WAIT_ABANDONED The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled.
    WAIT_OBJECT_0 The state of the specified object is signaled.
    WAIT_TIMEOUT The time-out interval elapsed, and the object's state is nonsignaled.
    Example:

       thr_hndl = CreateThread( NULL,
                                THRSTACKSIZE,
                                (LPTHREAD_START_ROUTINE)parallel_process,
                                NULL,
                                0,
                                &thr_id
       );
       ...
       if( thr_hndl != INVALID_HANDLE_VALUE )
          WaitForSingleObject(thr_hndl, INFINITE);
    

    Passing argument to the thread function

    As you saw above the fourth argument of a thread function is responsible for passing parameters to the function. The only problem is it can take only a pointer. Thus, to pass just one value of any type we need to store that value in a variable and pass the address of the variable. Do not forget to cast the pointer to the variable to a void pointer. Here is an example that passes a double value 15.5 to a thread. Please pay attention how thread handles this argument:
    DWORD thread_body(void *param)
    {
       double value = *(double*)param;
       cout<<"Thread got value "<<value<<" as an argument\n";
       ...
    }
    ...
    void main()
    {
       double param = 15.5;
       DWORD  thr_id;
       HANDLE thr_hndl;
       thr_hndl = CreateThread( NULL,
                                THRSTACKSIZE,
                                (LPTHREAD_START_ROUTINE)parallel_process,
                                (void*) &param,
                                0,
                                &thr_id
       );
       ...
    }
    
    If you need to pass several arguments to your thread you can create a structure, fill it in with the needed values and pass pointer to the structure to the thread. In the example below we are passing an integer, SOCKET, and a string to a thread:
    struct TThreadParams {
       int    tnumber;
       SOCKET s;
       char   name[128];
    }; 
    
    DWORD process_request(void* param)
    {
       THreadParams *p = (TThreadParam*) param;
       cout<<"My number: "<<p->number
           <<"My SOCKET: "<<p->s
           <<"My   name: "<<p->name<<endl;
    }
    ...
    void main()
    {
       TThreadParams prm;
       DWORD  thr_id;
       HANDLE thr_hndl;
       
       prm.number = 12;
       prm.s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
       strcpy(prm.name, "thread name");
       thr_hndl = CreateThread( NULL,
                                THRSTACKSIZE,
                                (LPTHREAD_START_ROUTINE)parallel_process,
                                (void*) &prm,
                                0,
                                &thr_id
       );
       ...
    }
    

    The following file contains an example that illustrates how to use all functions mentioned above.