Win32 - 使用CreateThread()创建线程

发布时间 2023-09-26 15:22:55作者: [BORUTO]

在window环境下,Win32 提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作:

1. 主要的函数列表

序号

函数名

功能

1

CreateThread()

创建一个新线程

2

ExitThread()

正常结束一个线程的执行

3

TerminateThead()

强制终止一个线程的执行

4

ResumeThread()

重启一个线程

5

SuspendThread()

挂起一个线程

6

GetExiCodeThread()

得到一个线程的退出码

7

GetThreadPriority()

得到一个线程的优先级

8

SetThreadPriority()

设置一个线程的优先级

9

CloseHandle()

关闭一个线程的句柄

10

CreateRemoteThread()

再另一个进程中创建一个新线程

11

PostThreadMessage()

发送一条消息给指定的线程

12

GetCurrentThread()

得到当前的线程句柄

13

GetCurrentThreadId()

得到当前线程的ID

14

GetThreadId()

得到指定线程的ID

15

WaitForSingleObject()

等待单个对象

16

WaitForMultipleObjects()

等待多个对象

关于多线程的API函数还有很多,以上只是列出了一些比较常用的函数,欲知更多函数和函数的使用方法,请参考MSDN或网络资源,在此就不再介绍了。

 

CreateThread函数原型:

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes, // 不重要,一般设置为NULL
  SIZE_T                  dwStackSize,        // 堆栈大小,不重要,一般设置为0,表示使用默认堆栈大小
  LPTHREAD_START_ROUTINE  lpStartAddress,     // 函数指针,传入函数名或指针即可
  __drv_aliasesMem LPVOID lpParameter,        // 参数指针,供函数使用
  DWORD                   dwCreationFlags,    // 不重要,一般设置为0
  LPDWORD                 lpThreadId          // 指针,用于保存线程的id,一般设置为NULL
);

参数说明:

lpThreadAttributes:指向SECURITY_ATTRIBUTES 结构的指针,该结构确定子进程是否可以继承返回的句柄。如果 lpThreadAttributes为NULL,则无法继承句柄。

dwStackSize:堆栈的初始大小,以字节为单位。系统将此值四舍五入到最近的页面。如果此参数为0,则新线程使用可执行文件的默认大小,1M。

lpStartAddress:指向由线程执行的应用程序定义函数的指针。该指针表示线程的起始地址。

lpParameter:指向要传递给线程的变量的指针。

dwCreationFlags:控制线程创建的标志。详细看下图。

lpThreadId:指向接收线程标识符的变量的指针。如果此参数为 NULL,则不返回线程标识符。

返回值:

如果函数成功,则返回值是新线程的句柄。

如果函数失败,则返回值为NULL。

 

2. 创建线程

在 Windows API 中,一般使用 CreateThread() 函数创建线程。

创建一个不带参数的线程

#include<iostream>
#include<windows.h>

using namespace std;

// 编写了一个我的线程函数
DWORD WINAPI MyThread(LPVOID lpParamter)
{
	cout << "fuck the multithread !\n";
	return 0L;
}

int main ()
{
	// 创造线程
	CreateThread(NULL, 0, MyThread, NULL, 0, NULL);
	// 记得等待线程结束
	system("PAUSE");
	return 0;
}

 

创建一个带参线程:lpParam参数

下面是使用Windows API创建线程并打印数字并获取重要的线程信息的代码示例:

#include <iostream>
#include <Windows.h>
 
DWORD WINAPI ThreadFunction(LPVOID lpParam)
{
    // 获取当前线程ID
    DWORD threadId = GetCurrentThreadId();
    std::cout << "Thread ID: " << threadId << std::endl;
 
    // 获取线程传入的参数
    int threadParam = *(int*)lpParam;
    for (int i = 0; i < threadParam; i++)
    {
        std::cout << i << std::endl;
    }
    return 0;
}
 
int main()
{
    int num = 10;
 
    // 创建线程
    HANDLE hThread = CreateThread(NULL, 0, ThreadFunction, &num, 0, NULL);
    if (hThread == NULL)
    {
        cout << "Failed to create thread" << endl;
        return 1;
    }
 
    // 等待线程结束
    WaitForSingleObject(hThread, INFINITE);
 
    // 关闭线程句柄
    CloseHandle(hThread);
 
    return 0;
}

 

3. 线程通信

以下是通过共享变量实现线程间通信的代码示例:

#include <Windows.h>
#include <iostream>
 
DWORD WINAPI ThreadFunction1(LPVOID lpParam)
{
    int* sharedVariable = (int*)lpParam;
    while (true)
    {
        if (*sharedVariable == 0)
        {
            std::cout << "Thread 1: sharedVariable = " << *sharedVariable << std::endl;
            *sharedVariable = 1;
        }
    }
    return 0;
}
 
DWORD WINAPI ThreadFunction2(LPVOID lpParam)
{
    int* sharedVariable = (int*)lpParam;
    while (true)
    {
        if (*sharedVariable == 1)
        {
            std::cout << "Thread 2: sharedVariable = " << *sharedVariable << std::endl;
            *sharedVariable = 0;
        }
    }
    return 0;
}
 
int main()
{
    int sharedVariable = 0;
    HANDLE hThread1 = CreateThread(NULL, 0, ThreadFunction1, &sharedVariable, 0, NULL);
    HANDLE hThread2 = CreateThread(NULL, 0, ThreadFunction2, &sharedVariable, 0, NULL);
    WaitForMultipleObjects(2, &hThread1, TRUE, INFINITE);
    CloseHandle(hThread1);
    CloseHandle(hThread2);
    return 0;
}

在主函数中,我们调用了 CreateThread 函数创建了两个线程,将共享变量 sharedVariable 的地址作为参数传入。线程 1 和线程 2 都通过判断共享变量的值来实现通信,它们每当共享变量的值变化时都会输出当前的值。

在这个例子中,WaitForMultipleObjects函数将等待两个线程hThread1和hThread2完成,并且要求等待所有事件对象完成,因此参数bWaitAll的值为TRUE。并且dwMilliseconds的值为INFINITE,所以等待时间是无限的。