CreateThread 函数 (processthreadsapi.h)

创建在调用进程的虚拟地址空间内执行的线程。

若要创建在另一个进程的虚拟地址空间中运行的线程,请使用 CreateRemoteThread 函数。

语法

HANDLE CreateThread(
  [in, optional]  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  [in]            SIZE_T                  dwStackSize,
  [in]            LPTHREAD_START_ROUTINE  lpStartAddress,
  [in, optional]  __drv_aliasesMem LPVOID lpParameter,
  [in]            DWORD                   dwCreationFlags,
  [out, optional] LPDWORD                 lpThreadId
);

参数

[in, optional] lpThreadAttributes

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

lpSecurityDescriptor 结构的成员为新线程指定安全描述符。 如果 lpThreadAttributes 为 NULL,则线程将获取默认的安全描述符。 线程的默认安全描述符中的 ACL 来自创建者的主要令牌。

[in] dwStackSize

堆栈的初始大小(以字节为单位)。 系统将此值舍入到最近的页面。 如果此参数为零,则新线程使用可执行文件的默认大小。 有关详细信息,请参阅 线程堆栈大小

[in] lpStartAddress

指向由线程执行的应用程序定义函数的指针。 此指针表示线程的起始地址。 有关线程函数的详细信息,请参阅 ThreadProc

[in, optional] lpParameter

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

[in] dwCreationFlags

控制线程创建的标志。

价值 意义
0
创建后,线程会立即运行。
CREATE_SUSPENDED
0x00000004
线程以挂起状态创建,在调用 ResumeThread 函数之前不会运行。
STACK_SIZE_PARAM_IS_A_RESERVATION
0x00010000
dwStackSize 参数 指定堆栈的初始保留大小。 如果未指定此标志,dwStackSize 指定提交大小。

[out, optional] lpThreadId

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

返回值

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

如果函数失败,则返回值 NULL。 若要获取扩展的错误信息,请调用 GetLastError

请注意,即使 lpStartAddress 指向数据、代码或无法访问,CreateThread 也可能成功。 如果线程运行时起始地址无效,则会发生异常,线程将终止。 由于启动地址无效,线程终止作为线程进程的错误退出进行处理。 此行为类似于 CreateProcess的异步性质,即使进程引用无效或缺少动态链接库(DLL),也会创建该进程。

言论

进程可以创建的线程数受可用虚拟内存的限制。 默认情况下,每个线程都有一兆字节的堆栈空间。 因此,在没有 /3GB boot.ini 选项的情况下,无法在 32 位系统上创建 2,048 个或更多线程。 如果减小默认堆栈大小,可以创建更多线程。 但是,如果为每个处理器创建一个线程并生成应用程序维护上下文信息的请求队列,则应用程序将具有更好的性能。 在处理下一个队列中的请求之前,线程将处理队列中的所有请求。

使用 THREAD_ALL_ACCESS 访问权限创建新线程句柄。 如果在创建线程时未提供安全描述符,则使用正在创建线程的进程的主令牌为新线程构造默认安全描述符。 当调用方尝试使用 OpenThread 函数访问线程时,会根据此安全描述符评估调用方的有效令牌,以授予或拒绝访问。

在调用 GetCurrentThread 函数时,新创建的线程本身具有完全访问权限。

Windows Server 2003:线程对自身的访问权限是通过评估线程针对为线程构造的默认安全描述符创建的进程的主要令牌来计算的。 如果在远程进程中创建了线程,则使用远程进程的主要令牌。 因此,新创建的线程在调用 getCurrentThread时,可能会降低对自身的访问权限。 某些访问权限(包括 THREAD_SET_THREAD_TOKENTHREAD_GET_CONTEXT 可能不存在,从而导致意外失败。 因此,不建议在模拟其他用户时创建线程。

如果线程处于可运行状态(即未使用 CREATE_SUSPENDED 标志),则线程可以在 CreateThread 返回之前开始运行,尤其是在调用方收到创建的线程的句柄和标识符之前。

线程执行从 lpStartAddress 参数指定的函数开始。 如果此函数返回,则 DWORD 返回值用于终止对 ExitThread 函数的隐式调用中的线程。 使用 GetExitCodeThread 函数获取线程的返回值。

该线程是使用线程优先级 THREAD_PRIORITY_NORMAL创建的。 使用 GetThreadPrioritySetThreadPriority 函数获取和设置线程的优先级值。

当线程终止时,线程对象将达到信号状态,满足正在等待对象的任何线程。

线程对象一直保留在系统中,直到线程终止,并且通过调用关闭线程的所有句柄 CloseHandle

ExitProcessExitThreadCreateThreadCreateRemoteThread 函数以及启动进程(由 CreateProcess调用的结果)在进程中相互序列化。 一次只能在地址空间中发生其中一个事件。 这意味着存在以下限制:

  • 在进程启动和 DLL 初始化例程期间,可以创建新线程,但在为进程完成 DLL 初始化之前,它们不会开始执行。
  • 一个进程中只有一个线程可以同时在 DLL 初始化或分离例程中。
  • ExitProcess 在 DLL 初始化或分离例程中没有线程之前未完成。
调用 C 运行时库(CRT)的可执行文件中的线程应使用线程管理 _beginthreadex_endthreadex 函数,而不是 CreateThreadExitThread;这需要使用 CRT 的多线程版本。 如果使用 CreateThread 创建的线程调用 CRT,CRT 可能会在内存不足的情况下终止进程。

Windows Phone 8.1: Windows Phone 8.1 及更高版本的 Windows Phone 应用商店应用支持此功能。

Windows 8.1Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本中的 Windows 应用商店应用支持此函数。

例子

有关示例,请参阅 创建线程

要求

要求 价值
最低支持的客户端 Windows XP [桌面应用 |UWP 应用]
支持的最低服务器 Windows Server 2003 [桌面应用 |UWP 应用]
目标平台 窗户
标头 processthreadsapi.h(包括 Windows Server 2003、Windows Vista、Windows 7、Windows Server 2008 Windows Server 2008 R2 上的 Windows.h)
Kernel32.lib;Windows Phone 8.1 上的 WindowsPhoneCore.lib
DLL Kernel32.dll;Windows Phone 8.1 上的 KernelBase.dll

另请参阅

CloseHandle

CreateProcess

CreateRemoteThread

ExitProcess

ExitThread

GetExitCodeThread

GetThreadPriority

进程和线程函数

ResumeThread

SECURITY_ATTRIBUTES

SetThreadPriority

SuspendThread

ThreadProc

线程