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) ,也会创建进程。

注解

进程可以创建的线程数受可用虚拟内存的限制。 默认情况下,每个线程都有一 MB 的堆栈空间。 因此,如果没有 /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 初始化或分离例程中。
  • 在 DLL 初始化或分离例程中没有线程之前,ExitProcess 不会完成。
在可执行文件中调用 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 应用]
目标平台 Windows
标头 processthreadsapi.h (包括 Windows Server 2003 上的 Windows.h、Windows Vista、Windows 7、Windows Server 2008 Windows Server 2008 R2)
Library 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

线程