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:
DWORD WINAPI ThreadFunc( LPVOID );
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.
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);
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.
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);
}
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. |
thr_hndl = CreateThread( NULL,
THRSTACKSIZE,
(LPTHREAD_START_ROUTINE)parallel_process,
NULL,
0,
&thr_id
);
...
if( thr_hndl != INVALID_HANDLE_VALUE )
WaitForSingleObject(thr_hndl, INFINITE);
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*) ¶m,
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.