loading...

Windows System Programming: Create / Terminate Threads

tbhaxor profile image Gurkirat Singh ・3 min read

Hi, I hope you are loving this series, if you aren't I would love to hear from you.

Anyways, in previous post I have shown you how to work with processes in windows. Now in this post, I will show you how to create a thread inside a process. But before going further in coding, you should learn about threads.

A thread in operating system is an independent entity which runs inside the process. The program execution is considered as main thread, as because child threads are only created by processes and can be destroyed by them only. It shares some resources (like code, data and virtual address space) of the process (main thread) except STACK and CPU Registers. As per MSDN, you can create max 2048 threads for a process.

Read more about threads on MSDN → https://docs.microsoft.com/en-us/dotnet/standard/threading/threads-and-threading

You can create thread with CreateThread function and terminate the thread with TerminateThread function, both are declared in processthreadsapi.h and defined in Kernel32.lib

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  SIZE_T                  dwStackSize,
  LPTHREAD_START_ROUTINE  lpStartAddress,
  __drv_aliasesMem LPVOID lpParameter,
  DWORD                   dwCreationFlags,
  LPDWORD                 lpThreadId
);
Enter fullscreen mode Exit fullscreen mode

Parameters description as follows

  • lpThreadAttributes → A pointer to a SECURITY_ATTRIBUTES. If this is NULL, the thread handle cannot be inherited by child process.
  • dwStackSize → The initial size of the stack, in bytes. For more information see Thread Stack Size. If this parameter is 0x0, the new thread will use the default size for the executable.
  • lpStartAddress → A pointer to the application-defined thread call-back function. For more information see ThreadProc
  • lpParameter → A long void pointer to a variable to be passed to the thread. Since it is a void pointer, which means it will be generic pointer and should be dereferenced with particular type of data. If you don't want to pass any data, it should be set to NULL.
  • dwCreationFlags → The flags that control the creation of the thread. Most of the time it will be 0x0, which means the thread will immediately after creation.
  • lpThreadId → A pointer to a variable that receives the thread identifier. If this is NULL, thread ID is not returned
BOOL TerminateThread(
  HANDLE hThread,
  DWORD  dwExitCode
);
Enter fullscreen mode Exit fullscreen mode

Parameters description as follows

  • hThread rarr; A handle to the thread to be terminated with THREAD_TERMINATE access right
  • dwExitCode → The exit code for the thread.

Complete code as follows

#include <Windows.h>
#include <tchar.h>
#include <processthreadsapi.h>
#include <handleapi.h>
#include <synchapi.h>
#include <stdio.h>

// this is like call back function which is executed by create thread function
// WINAPI is the function signature
// LPVOID params will be NULL as, I have passed 4th parameter NULL in create thread function but is required for function definition
DWORD WINAPI Worker(LPVOID params) {

    // worker function body
    while (true)
    {
        _tprintf(_T("Running Thread\n"));
        Sleep(500);
    }

    return 0;
}

int _tmain(int argc, TCHAR** argv) {

    DWORD threadId;

    // creating thread
    // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread
    HANDLE hThread = CreateThread(NULL, 0x0, Worker, NULL, 0, &threadId);
    _tprintf(_T("Thread ID: %d\n"), threadId);
    _tprintf(_T("Enter 'q' to exit\n"));

    if (hThread == NULL || hThread == INVALID_HANDLE_VALUE) {
        _tprintf(_T("Unable to create thread\n"));
        return 1;
    }

    CHAR ch;
    while (true) {
        scanf_s("%c", &ch, 1);
        if (ch == 'q') {
#pragma warning(disable : 6258 6387 6001)
            // terminate the thread
            // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminatethread
            TerminateThread(hThread, 0x0);

#pragma warning(disable : 6387)
            // this is required as TerminateThread does not perform proper thread clean-up
            CloseHandle(hThread);

            // break out of loop
            _tprintf(_T("Thread is closed. Closing main application in 3 seconds\n"));
            Sleep(3000);
            break;
        }
    }

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

You might be wondering what does this WINAPI do. Read the stackoverflow answer about this.

Thanks for reading this post. Follow the links to reach me

Discussion

pic
Editor guide