极语言官方网站

同步异步——使用介绍

若要同步对资源的访问,请在其中一个等待函数中使用其中一个同步对象。
同步对象的状态为 已发出信号 或 未签名。
等待函数允许线程阻止自身的执行,直到指定的未签名对象设置为信号状态。
有关详细信息,请参阅 进程间同步。

等待函数

等待函数允许线程阻止其自己的执行。在满足指定条件之前不会返回。 等待函数的类型确定所使用的条件集。调用时会检查是否已满足等待条件。 如果未满足条件,则调用线程将进入等待状态,直到满足等待条件的条件或指定的超时间隔已过。 单对象等待函数 对象等单、等单对象 和 等待对象 函数需要一个同步对象的句柄。 发生以下任一情况时,这些函数将返回: 指定的对象处于已发出信号的状态。 超时间隔已过。 超时间隔可以设置为0xFFFFFFFF,以指定等待不会超时。 对象等单 函数使调用线程能够以原子方式将对象的状态设置为信号,并等待另一个对象的状态设置为信号。 多对象等待函数 等多对象、等列对象、等多消息 和 等列消息 函数使调用线程能够指定包含一个或多个同步对象句柄的数组。 发生以下任一情况时,这些函数将返回: 任何一个指定对象的状态都设置为“已发出信号”,或者所有对象的状态都已设置为“已发出信号”。 你可以控制在函数调用中使用一种还是所有状态。 超时间隔已过。 超时间隔可以设置为 0xFFFFFFFF ,以指定等待不会超时。 使用 等多消息 和 等列消息 函数,可以在对象句柄数组中指定输入事件对象。 这是在线程的输入队列中指定要等待的输入类型时完成的。例如,线程可以使用 等多消息 阻止其执行,直到指定对象的状态设置为已发出信号,并且线程的输入队列中有可用的鼠标输入。 可以使用 获取消息 或 查探消息 函数来检索输入。 当等待所有对象的状态设置为信号时,这些多对象函数不会修改指定对象的状态,直到所有对象的状态都已设置信号。 例如,可以向互斥对象的状态发出信号, 但在数组中指定的其他对象的状态也设置为信号之前,调用线程不会获得所有权。 同时,其他一些线程可能会获得互斥对象的所有权,从而将其状态设置为非签名。 在等待单个对象的状态设置为信号时,这些多对象函数检查数组中的句柄,从索引 0 开始,直到向其中一个对象发出信号。 如果多个对象被发出信号,函数将返回数组中第一个句柄的索引,该句柄已发出对象信号。 可警报等待函数 等列消息、对象等单、等列对象 和 等待对象 函数与其他等待函数不同,因为它们可以选择执行可警报的等待操作。 在可发出警报的等待操作中, 函数可以在满足指定条件时返回,但如果系统将 I/O 完成例程或 APC 排队等待线程执行,函数也可以返回。 已注册的等待函数 列线程池 函数与其他等待函数的不同之处在于,等待操作由线程池中的线程执行。 满足指定条件时,回调函数由线程池中的工作线程执行。 默认情况下,已注册的等待操作是多等待操作。 每次向事件发出信号时,系统都会重置计时器 (或超时间隔) ,直到调用 注销等待 函数来取消操作。 若要指定等待操作应只执行一次,请将 列线程池 的 标志 参数设置为 8。 如果线程调用使用 APC 的函数,请将 列线程池 的 标志 参数设置为 0x80。 正在等待地址 线程可以使用 WaitOnAddress 函数来等待目标地址的值从某些不需要的值更改为任何其他值。 这使线程能够等待值更改, 而无需旋转或处理线程捕获不需要的值但值更改后线程可以等待时可能出现的同步问题。 当修改目标值的代码通过调用 WakeByAddressSingle 来唤醒单个等待线程或调用 WakeByAddressAll 来唤醒所有等待线程 来发出更改信号时,WaitOnAddress 将返回。 如果使用 WaitOnAddress 指定了超时间隔,并且没有线程调用唤醒函数,则当超时间隔过后,该函数将返回。 如果未指定超时间隔,则线程将无限期等待。 等待函数和超时间隔 指定超时间隔的准确性取决于系统时钟的分辨率。系统时钟以恒定速率“滴答”。 如果超时间隔小于系统时钟的分辨率,则等待可能会少于指定的时间长度。 如果超时间隔大于一个刻度,但小于两个刻度周期,则等待时间可以是介于 1 和 2 个刻度之间的任意位置,依此类比。 若要提高等待函数超时间隔的准确性,请调用 timeGetDevCaps 函数来确定支持的最小计时器分辨率, 并调用 timeBeginPeriod 函数将计时器分辨率设置为其最小值。 调用 timeBeginPeriod 时请谨慎,因为频繁调用可能会显著影响系统时钟、系统电源使用情况和计划程序。 如果调用 timeBeginPeriod,请在应用程序早期调用一次,并确保在应用程序最末尾调用 timeEndPeriod 函数。 等待函数和同步对象 等待函数可以修改某些类型的 同步对象的状态。 仅针对其信号状态导致函数返回的对象或对象进行修改。 等待函数可以修改同步对象的状态,如下所示: 信号灯对象的计数将减少一个,如果信号量计数为零,则信号灯的状态将设置为无信号。 互斥、自动重置事件和更改通知对象的状态设置为不对齐。 同步计时器的状态设置为“未签名”。 手动重置事件、手动重置计时器、进程、线程和控制台输入对象的状态不受等待函数的影响。 等待函数和创建窗口 使用直接或间接创建窗口的等待函数和代码时必须小心。 如果线程创建任何窗口,它必须处理消息。 消息广播将发送到系统中的所有窗口。 如果有一个线程使用没有超时间隔的等待函数,系统会死锁。 间接创建窗口的两个代码示例是 DDE 和 初始化库 函数。 因此,如果你有创建窗口的线程,请使用 等多消息 和 等列消息,而不是其他等待函数。

同步对象

同步对象是一个对象,可以在其中一个等待函数中指定其句柄,以协调多个线程的执行。

多个进程可以具有同一同步对象的句柄,使进程间同步成为可能。

以下对象类型专用于同步。

类型说明
事件 通知一个或多个正在等待的线程已发生事件。 有关详细信息,请参阅 事件对象
Mutex 一次只能由一个线程拥有,使线程能够协调对共享资源的互斥访问。 有关详细信息,请参阅 互斥对象
Semaphore 维护零和某个最大值之间的计数,从而限制同时访问共享资源的线程数。 有关详细信息,请参阅 Semaphore 对象
可等待计时器 通知一个或多个等待线程已到达指定时间。 有关详细信息,请参阅 可等待计时器对象

以下对象虽然可用于其他用途,但也可用于同步。

对象说明
更改通知 由 初改通知 函数创建,其状态设置为在指定目录或目录树中发生指定类型的更改时发出信号。 有关详细信息,请参阅 获取目录更改通知
控制台输入 在创建控制台时创建。 指定 CONIN$ 时,创建文件 函数或 取控制台 函数返回控制台输入的句柄。 当主机的输入缓冲区中存在未读输入时,
其状态设置为信号;当输入缓冲区为空时,其状态设置为“未对齐”。 有关控制台的详细信息,请参阅 字符模式应用程序
作业 通过调用 创建作业 函数创建。 作业对象的状态设置为在终止其所有进程时发出信号,因为已超出指定的作业结束时间限制。 有关作业对象的详细信息,请参阅 作业对象
内存资源通知 由 内存通知 函数创建。 其状态设置为在物理内存中发生指定类型的更改时发出信号。 有关内存的详细信息,请参阅 内存管理
进程 通过调用 创建进程 函数创建。 进程运行时,其状态设置为“未对齐”,并在进程终止时设置为“已发出信号”。 有关进程的详细信息,请参阅 进程和线程
线程 通过调用 创建进程、 创建线程 或 远程线程 函数创建新线程时创建。 当线程运行时,其状态设置为“非对齐”,并在线程终止时设置为“已发出信号”。 有关线程的详细信息,请参阅 进程和线程

在某些情况下,还可以使用文件、命名管道或通信设备作为同步对象;但是,不建议将其用于此目的。

请改用异步 I/O 并等待 在 OVERLAPPED 结构中设置的事件对象

使用事件对象更安全,因为在同一文件、命名管道或通信设备上执行多个同时重叠操作时,可能会出现混淆。

在这种情况下,无法知道哪个操作导致对象状态被发出信号。

事件对象

事件对象是一个同步对象,其状态可以通过使用 修改事件 函数显式设置为发出信号。
下面是两种类型的事件对象。
手动重置事件对象,其状态在 重置事件 函数显式重置为非信号之前保持信号。
发出信号时,可以释放任意数量的等待线程或随后在其中一个 等待函数中指定相同事件对象的线程。
自动重置事件对象,其状态一直保持信号,直到释放单个等待线程,此时系统会自动将状态设置为未签名。
如果没有线程在等待,则事件对象的状态将保持已发信号状态。
如果有多个线程正在等待,则选择一个等待线程。 不要假设先入先出 (FIFO) 顺序。
外部事件(如内核模式 APC)可以更改等待顺序。
事件对象在向线程发送指示已发生特定事件的信号时很有用。
例如,在重叠的输入和输出中,当重叠操作完成时,系统会将指定的事件对象设置为信号状态。
单个线程可以在多个同时重叠的操作中指定不同的事件对象,
然后使用其中一个多对象 等待函数 来等待任何一个事件对象的状态被发出信号。
线程使用 创建事件 或 新建事件 函数创建事件对象。
创建线程指定对象的初始状态,以及它是手动重置事件对象还是自动重置事件对象。
创建线程还可以指定事件对象的名称。
其他进程中的线程可以通过在对 打开事件 函数的调用中指定其名称来打开现有事件对象的句柄。
有关互斥体、事件、信号灯和计时器对象的名称的其他信息,请参阅 进程间同步。
 

互斥对象

互斥对象是一个同步对象,当它不受任何线程拥有时,其状态设置为信号;
当它拥有时,状态设置为信号。 一次只有一个线程可以拥有互斥对象,
该对象的名称来自这样一个事实,即它有助于协调对共享资源的互斥访问。
例如,为了防止两个线程同时写入共享内存,
每个线程先等待互斥对象的所有权,然后再执行访问内存的代码。
写入共享内存后,线程释放互斥对象。
线程使用 创建互斥 或 新建互斥 函数创建互斥对象。
创建线程可以请求互斥对象的即时所有权,还可以指定互斥对象的名称。
它还可以创建未命名的互斥体。 有关互斥体、事件、信号量和计时器对象的名称的其他信息,请参阅 进程间同步。

其他进程中的线程可以通过在调用 打开互斥 函数时指定其名称来打开现有命名互斥对象句柄。
若要将句柄传递给未命名的互斥体到另一个进程,请使用 复制对象 函数或父子句柄继承。

具有互斥对象句柄的任何线程都可以使用 等待函数 之一来请求互斥对象的所有权。
如果互斥对象由另一个线程拥有,则等待函数会阻止请求线程,
直到拥有的线程使用 释放互斥 函数释放互斥对象。
等待函数的返回值指示函数是否返回的原因,而不是设置为信号的互斥状态。

如果多个线程正在等待互斥体,则会选择一个正在等待的线程。
不要假定先入先出 (FIFO) 顺序。 外部事件(如内核模式 APC)可以更改等待顺序。

线程获得互斥体的所有权后,它可以在对等待函数的重复调用中指定相同的互斥,而不会阻止其执行。
这可以防止线程在等待它已拥有的互斥体时自行死锁。
若要在此类情况下释放其所有权,每次互斥体满足等待函数的条件时,线程都必须调用 释放互斥 一次。

如果线程终止而不释放其互斥对象的所有权,则互斥对象被视为已放弃。
等待线程可以获取已放弃互斥对象的所有权,但等待函数将返回 0x80 指示互斥对象已放弃。
放弃的互斥对象表示发生了错误,并且受互斥对象保护的任何共享资源都处于未定义状态。
如果线程未放弃互斥对象,在线程释放其所有权后,不再将其视为已放弃。
如果随后在等待函数中指定互斥对象的句柄将还原正常行为。
请注意关键节对象 提供的同步类似于互斥对象提供的同步,只是关键节对象只能由单个进程的线程使用。

信号灯对象

信号灯对象是保持零和指定最大值之间的计数的同步对象。
每次线程完成等待信号灯对象时,计数都会递减,每次线程释放信号灯时计数都会递增。当计数达到零时,
没有更多的线程可以成功等待信号灯对象状态变为信号。
当计数大于零时,会将信号量的状态设置为已发出信号;当计数为零时,会将信号量的状态设置为未发出信号。

信号灯对象可用于控制可支持有限数量的用户的共享资源。
它充当一个入口,将共享资源的线程数限制为指定的最大数目。
例如,应用程序可能会限制其创建的窗口数。
它使用最大计数等于窗口限制的信号灯,每次创建窗口时递减计数,并在窗口关闭时递增。
应用程序在创建每个窗口之前,在调用其中一个等待函数 时指定信号灯对象。
当计数为零(指示已达到窗口限制)时,等待函数将阻止执行窗口创建代码。

线程使用 创建信号 或 新建信号 函数创建信号灯对象。
创建线程指定对象的初始计数和最大值。
初始计数不能小于零,也不能大于最大值。
创建线程还可以指定信号灯对象的名称。
其他进程中的线程可以通过在调用 打开信号 函数时指定其名称来打开现有信号灯对象的句柄。 

如果多个线程正在一个信号灯上等待,则会选择一个等待的线程。
不要假设先入先出 (FIFO) 顺序。 外部事件(如内核模式 APC)可以更改等待顺序。

每当一个 等待函数 返回时,由于信号灯的状态设置为信号,信号灯的计数将减少 1。
信号增量 函数将信号灯的计数增加指定的量。 计数不能小于零或大于最大值。

信号灯的初始计数通常设置为最大值。随着受保护资源的消耗,计数将从该级别递减。
可以创建初始计数为零的信号灯,以在初始化应用程序时阻止对受保护资源的访问。
初始化后,可以使用 信号增量 将计数递增到最大值。

拥有互斥对象的线程可以重复等待同一互斥对象成为信号,而不会阻止其执行。
但是,如果线程重复等待同一信号灯对象,则每次完成等待操作时都会递减信号灯的计数;
当计数为零时,线程被阻止。 同样,只有拥有互斥体的线程才能成功调用 释放互斥 函数,
但任何线程都可以使用 信号增量 来增加信号灯对象的计数。

线程可以在调用任何 等待函数时重复指定同一信号灯对象,从而多次递减信号灯的计数。
但使用包含同一信号灯的多个句柄的数组调用其中一个多对象等待函数不会导致多次递减。

使用完信号灯对象后,调用 关闭对象 函数以关闭句柄。
信号灯对象在其最后一个句柄已关闭时被销毁。 关闭句柄不会影响信号灯计数;
因此,请确保在关闭句柄之前或进程终止之前调用 信号增量 。
否则,挂起的等待操作将超时或无限期地继续,具体取决于是否已指定超时值。

可等待计时器对象

可等待计时器对象是同步对象,其状态设置为在指定的到期时间到达时发出信号。
可以创建两种类型的可等待计时器:手动重置和同步。计时器也可以是定期计时器。
手动重置计时器,其状态在调用 设置延时 以建立新的到期时间之前保持信号。
同步计时器	在线程完成对计时器对象的等待操作之前,其状态保持信号的计时器。
定期计时器,该计时器在每次指定的时间段过期时重新激活,直到计时器重置或取消。
是定期手动重置计时器或定期同步计时器。

备注
当计时器发出信号时,处理器必须运行 来处理关联的指令。
高频率定期计时器使处理器持续繁忙,从而防止系统在任何有意义的时间内保持低功耗 状态 。
这可能对便携式计算机的电池使用时间和依赖于有效电源管理的方案(如大型数据中心)产生负面影响。
为了提高能效,请考虑在应用程序中使用基于事件的通知,
而不是基于时间的通知。
如果需要计时器,请使用发出一次信号的计时器而不是定期计时器,或将间隔设置为大于 1 秒的值。

线程使用 创建延时 或 新建延时 函数创建计时器对象。
创建线程指定计时器是手动重置计时器还是同步计时器。 创建线程可以指定计时器对象的名称。
其他进程中的线程可以通过在对打开延时函数的调用中指定其名称来打开现有计时器的句柄。
具有计时器对象句柄的任何线程都可以使用等待计时器状态设置为信号。

线程调用 设置延时 函数来激活计时器。 请注意, 设置延时 使用以下参数:
使用 时间 参数指定计时器设置为信号状态的时间。 
当手动重置计时器设置为信号状态时,它将保持此状态,直到 设置延时 建立新的到期时间。
当同步计时器设置为信号状态时,它将保持此状态,直到线程完成对计时器对象的等待操作。
使用 设置延时 函数的 周期 参数指定计时器周期。
如果句点不为零,则计时器为定期计时器;每次期限到期时,都会重新激活该计时器,直到计时器重置或取消。
如果周期为零,则计时器不是定期计时器;它发出一次信号,
然后停用。线程可以使用 取消延时 函数将计时器设置为非活动状态。
若要重置计时器,请调用 设置延时。 完成计时器对象后,调用 关闭对象 以关闭计时器对象的句柄。

可等待计时器的行为可以汇总如下:

设置计时器时,如果计时器已处于活动状态,计时器状态为未签名,
并且计时器放置在内核计时器队列中,则会取消该计时器。
当计时器过期时,计时器将设置为信号状态。如果计时器具有完成例程,则会将其排队到设置计时器的线程。
完成例程保留在线程的异步过程调用 (APC) 队列中,
直到线程进入可发出警报的等待状态。 此时,将调度 APC 并调用完成例程。
如果计时器是定期的,则将其放回内核计时器队列中。
取消计时器后,如果某个计时器处于挂起状态,则会将其从内核计时器队列中删除。如果计时器已过期,
并且仍有 APC 排队到设置计时器的线程,则 APC 将从该线程的 APC 队列中删除。 计时器的信号状态不受影响。

同步对象安全性和访问权限

使用 Windows 安全模型可以控制对事件、互斥体、信号灯和可等待计时器对象的访问。
计时器队列、互锁变量和关键节对象是不安全的。
调用 创建事件、创建互斥、创建信号 或 创建延时 函数时,可以为进程间同步对象指定安全描述符。
如果指定0,则对象将获取默认的安全描述符。
同步对象的默认安全描述符中 ) 访问控制列表 (ACL 来自创建者的主令牌或模拟令牌。

若要获取或设置事件、互斥体、信号灯或可等待计时器对象的安全描述符,
请调用 取名安全、改名安全、取安全符 或 改安全符 函数。
创建事件、创建互斥、创建信号 或 创建延时 返回的句柄对新对象具有完全访问权限。
调用 打开事件、打开互斥、打开信号 或 打开延时 函数时,
系统会根据对象的安全描述符检查请求的访问权限。
进程间同步对象的有效访问权限包括 标准访问权限 和某些特定于对象的访问权限。
下表列出了所有对象使用的标准访问权限。

英文名称数值作用
DELETE0x00010000删除对象所必需的。
READ_CONTROL0x00020000需要读取对象的安全描述符中的信息,不包括 SACL 中的信息。 若要读取或写入 SACL,必须请求 0x01000000 访问权限。
WRITE_DAC0x00040000需要修改对象的安全描述符中的 DACL。
WRITE_OWNER0x00080000需要更改对象的安全描述符中的所有者。
SYNCHRONIZE0x00100000将对象用于同步的权限。 这使线程能够等待对象处于信号状态。

下表列出了事件对象的特定对象访问权限。

除了标准访问权限外,还支持这些权限。

英文名称数值作用
EVENT_ALL_ACCESS0x1F0003事件对象的所有可能访问权限。 仅当应用程序需要超出标准访问权限和2 EVENT_MODIFY_STATE授予的访问权限时,才使用此权限。 使用此访问权限会增加必须由管理员运行应用程序的可能性。
EVENT_MODIFY_STATE0x0002修改 SetEvent、ResetEvent 和 PulseEvent 函数所需的状态访问。

下表列出了互斥对象的特定对象访问权限。

除了标准访问权限外,还支持这些权限。

英文名称数值作用
MUTEX_ALL_ACCESS0x1F0001互斥对象的所有可能访问权限。 仅当应用程序需要超出标准访问权限授予的访问权限时,才使用此权限。 使用此访问权限会增加必须由管理员运行应用程序的可能性。
MUTEX_MODIFY_STATE0x0001保留供将来使用。

下表列出了信号灯对象的特定于对象的访问权限。

除了标准访问权限外,还支持这些权限。

英文名称数值作用
SEMAPHORE_ALL_ACCESS0x1F0003信号灯对象的所有可能访问权限。 仅当应用程序需要超出标准访问权限和 SEMAPHORE_MODIFY_STATE授予的访问权限时,才使用此权限。 使用此访问权限会增加必须由管理员运行应用程序的可能性。
SEMAPHORE_MODIFY_STATE0x0002修改 信号增量 函数所需的状态访问。

下表列出了可等待计时器对象的特定于对象的访问权限。

除了标准访问权限外,还支持这些权限。

英文名称数值作用
TIMER_ALL_ACCESS0x1F0003可等待计时器对象的所有可能访问权限。 仅当应用程序需要超出标准访问权限和 TIMER_MODIFY_STATE授予的访问权限时,才使用此权限。 使用此访问权限会增加必须由管理员运行应用程序的可能性。
TIMER_MODIFY_STATE0x0002修改 设置延时 和 取消延时 函数所需的状态访问。
TIMER_QUERY_STATE0x0001保留供将来使用。

进程间同步

多个进程可以具有同一事件、互斥体、信号量或计时器对象的句柄,因此这些对象可用于完成进程间同步。
创建对象的过程可以使用 创建事件、创建互斥、创建信号 或 创建延时 函数返回的句柄。
其他进程可以使用对象名称或通过继承或复制来打开对象的句柄。

对象名称
命名对象为进程提供了一种简单的方法来共享对象句柄。
进程创建命名事件、互斥体、信号灯或计时器对象后,其他进程可以使用名称调用相应的函数,
(打开事件、打开互斥、打开信号 或 打开延时) 打开对象的句柄。 名称比较区分大小写。

事件、信号灯、互斥体、可等待计时器、文件映射和作业对象的名称共享相同的命名空间。
如果尝试使用由另一种类型的对象使用的名称创建对象,该函数将失败,
并且 最后错误 将返回 6。 因此,创建命名对象时,请使用唯一名称,并确保检查重复名称错误的函数返回值。

如果尝试使用同类型对象正在使用的名称创建对象,则函数会成功,返回现有对象的句柄, 最后错误 将返回 183。
例如,如果在对 创建互斥 函数的调用中指定的名称与现有互斥对象的名称匹配,则函数将返回现有对象的句柄。
在这种情况下,对 创建互斥 的调用等效于对 打开互斥 函数的调用。 因此,让多个进程对同一互斥使用 
创建互斥 等效于让一个进程调用 创建互斥 ,而另一个进程调用 打开互斥,只不过它不需要确保先启动创建过程。
但是,当将此技术用于互斥对象时,任何调用进程都不应立即请求互斥体的所有权。
如果多个进程确实请求即时所有权,则很难预测哪个进程实际获得初始所有权。

终端服务环境具有事件、信号灯、互斥体、可等待计时器、文件映射对象和作业对象的全局命名空间。
对于这些对象,每个终端服务客户端会话都有其自己的单独命名空间。
终端服务客户端进程可以使用带有“Global\”或“Local\”前缀的对象名称在全局命名空间或会话命名空间中显式创建对象。
有关详细信息,请参阅 内核对象命名空间。
使用终端服务会话实现快速用户切换, (每个用户登录到不同的会话) 。
内核对象名称必须遵循终端服务概述的准则,以便应用程序可以支持多个用户。
可以在专用命名空间中创建同步对象。 有关详细信息,请参阅 对象命名空间。

对象命名空间
对象命名空间保护命名对象免受未经授权的访问。
创建专用命名空间使应用程序和服务能够构建更安全的环境。
进程可以使用 创建私名 函数创建专用命名空间。
此函数要求指定一个边界,该 边界 定义如何隔离命名空间中的对象。
调用方必须在指定的边界内才能成功执行创建操作。
若要指定边界,请使用 创建边字 和 安号边字 函数。
创建私名 的 前缀 参数用作命名空间的名称。
每个命名空间都由其名称和边界唯一标识。
只要指定不同的边界,系统就支持多个同名的专用命名空间。

假设某个进程请求创建命名空间 NS1,该命名空间定义包含两个元素的边界:管理员 SID 和当前会话编号。
如果进程在指定会话中的管理员帐户下运行,
则会创建命名空间。另一个进程可以使用 打开私名 函数访问此命名空间。
如果此进程要打开由第一个进程创建的命名空间,则指定的名称和边界必须匹配。
请注意,进程可以打开现有命名空间,即使它不在边界内,除非创建者使用 安属 参数限制对命名空间的访问。

在此命名空间中创建的对象的名称采用 前缀\对象名 的形式。
前缀是由 创建私名 的 前缀 参数指定的命名空间名称。
例如,若要在 NS1 命名空间中创建名为 MyEvent 的事件对象,
请调用 创建事件 函数,并将 名称 参数设置为 NS1\MyEvent。

创建命名空间的进程可以使用 关闭私名 函数关闭命名空间的句柄。
创建命名空间的进程终止时,句柄也会关闭。
关闭命名空间句柄后,对 打开私名 的后续调用将失败,但对命名空间中的对象执行的所有操作都会成功。

对象继承
使用 创建进程 函数创建进程时,可以使用 安全属性类 结构指定进程继承互斥、事件、信号灯或计时器对象的句柄。
进程继承的句柄对 对象具有与原始句柄相同的访问权限。
继承的句柄显示在已创建进程的句柄表中,但您必须将句柄值传达给创建的进程。
可以通过在调用 创建进程 时将值指定为命令行参数来执行此操作。
然后,创建的进程使用 启动参数 函数检索命令行字符串,
并将 句柄 参数转换为可用句柄。 有关详细信息,请参阅继承对象重复
复制对象 函数创建可由另一个指定进程使用的重复句柄。
这种共享对象句柄的方法比使用命名对象或继承更为复杂。
它需要创建过程和在其中复制句柄的进程之间的通信。 
(句柄值和进程标识符) 的必要信息可以通过任何进程间通信方法(如命名管道或命名共享内存)进行通信。

同步和多处理器问题

应用程序在多处理器系统上运行时可能会遇到问题,因为他们所做的假设仅在单处理器系统上有效。

线程优先级
想象一下具有两个线程的程序,一个线程优先级高于另一个线程。
在单处理器系统上,高优先级线程不会将控制权让与低优先级线程,
因为计划程序会将优先权赋予优先级较高的线程。
在多处理器系统上,两个线程都可以同时运行,每个线程在其自己的处理器上运行。
应用程序应同步对数据结构的访问,以避免争用情况。
假定高优先级线程不受较优先级线程干扰的代码将在多处理器系统上失败。

内存排序
当处理器写入内存位置时,将缓存该值以提高性能。
同样,处理器会尝试满足缓存中的读取请求以提高性能。 
此外,处理器开始从内存中提取值,然后再由应用程序请求这些值。
这可能在推理执行过程中发生,也可能是由于缓存行问题造成的。

CPU 缓存可以进行分区以分为多个可以并行访问的库。
这意味着内存操作可能会无序完成。
为了确保内存操作有序完成,大多数处理器都提供内存屏障指令。
完整内存屏障可确保内存屏障指令之前出现的内存读取和写入操作在内存屏障指令之后出现的
任何内存读取和写入操作之前提交到内存。
读取内存屏障只对内存读取操作进行排序,而写入内存屏障只对内存写入操作进行排序。
这些指令还可确保编译器禁用可能会跨屏障进行内存操作重新排序的任何优化。

处理器可以支持具有获取、释放和围栏语义的内存屏障指令。 这些语义描述了操作结果变得可用的顺序。
使用获取语义,该操作的结果会在代码中后出现的
任何操作的结果之前可用。使用释放语义,该操作的结果会在代码中先出现的任何操作的结果之后可用。
围栏语义结合了获取和释放语义。
具有围栏语义的操作的结果在代码中后出现的任何操作的结果之前以及先出现的任何操作的结果之后可用。

在支持 SSE2 的 x86 和 x64 处理器上,指令是 mfence(内存围栏)、lfence(负载围栏)和 sfence(存储围栏)。
在 ARM 处理器上,指令是 dmb 和 dsb。 
以下同步函数使用适当的屏障来确保内存排序:
进入或离开关键部分的函数
获取或释放 SRW 锁的函数
一次性初始化开始和完成
等待屏障 函数
向同步对象发出信号的函数
等待函数
互锁函数(具有 NoFence 后缀的函数或具有 _nf 后缀的内部函数除外)

修复争用条件
以下代码在多处理器系统上存在争用条件,因为首次执行 缓存计算值 的处理器可能会
在将 值 写入主内存之前将 已计算值 写入主内存。
因此,同时执行 获取计算值 的第二个处理器会将 已计算值 读取为 真,
但 值 的新值仍位于第一个处理器的缓存中,并且尚未写入内存。
整数 值,已计算值,算值;
程序段 缓存计算值
  如果(已计算值=0) 
  {
    值 = 算值
    计算 = 真
  }
结束
 
程序段 获取计算值(反馈)
  如果(已计算值) 
  {
    反馈& = 值
    返回(真)
  } 
  否则 返回(假)
结束
可以使用 原子更改 函数修复上述争用条件,以确保所有处理器在 计算 的值设置为 真 之前已更新 值 的值。

整数 值,已计算值,算值;
程序段 缓存计算值
  如果(原子比较(@已计算值,假,假)=0) 
  {
    原子更改(@值,算值)
    原子更改(@已计算值,真)
  }
结束
 
程序段 获取计算值(反馈)
  如果(原子比较(@计算,真,真)) 
  {
    原子更改(反馈&,值)
    返回(真)
  } 
  否则 返回(假)
结束

同步和重叠输入和输出

可以在文件、命名管道和串行通信设备上执行同步或异步 (也称为重叠) I/O 操作。
写出文件、读取文件、硬件控制、串口等待、连接管道
和 名管读写 函数可以同步或异步执行。 读入文件 和 写入文件 函数只能异步执行。

当函数同步执行时,该函数在操作完成之前不会返回。
这意味着,在等待耗时的操作完成时,调用线程的执行可能会无限期地被阻止。
为重叠操作调用的函数可以立即返回,即使操作尚未完成。
这样,当调用线程可以自由执行其他任务时,就可以在后台执行耗时的 I/O 操作。
例如,单个线程可以在不同的句柄上同时执行 I/O 操作,甚至可以在同一句柄上同时执行读取和写入操作。
若要将其执行与重叠操作的完成同步,
调用线程使用 操作结果 函数、 重叠结果 函数或 等待函数 之一来确定重叠操作何时完成。
还可以使用 重叠类.状态!=0x103 轮询完成。

若要取消所有挂起的异步 I/O 操作,请使用 取消传输 函数并提供用于指定要取消的请求的 重叠类 结构。
使用 取消操作 函数可取消由指定文件句柄的调用线程发出的挂起异步 I/O 操作。

重叠操作需要使用 0x40000000 标志创建的文件、命名管道或通信设备。
当线程调用函数 ((如 读取文件 函数) )来执行重叠操作时,
调用线程必须指定指向 重叠类 结构的指针。
(如果此指针为 NULL,则函数返回值可能会错误地指示操作已完成。) 
除非使用事件来指示 I/O 操作完成,否则 必须将 重叠类 结构的所有成员初始化为零。
如果使用事件,则 重叠类
 结构的 事件 成员将指定已分配事件对象的句柄。
 当对 I/O 函数的调用在操作完成之前返回时,系统会将事件对象的状态设置为非签名。
 系统将事件对象的状态设置为在操作完成时发出信号。
 仅当同时有多个未完成的 I/O 操作时,才需要事件。
 如果未使用事件,则每个已完成的 I/O 操作都将向文件、命名管道或通信设备发出信号。

调用函数以执行重叠操作时,该操作可能在函数返回之前完成。
发生这种情况时,将像同步执行操作一样处理结果。
但是,如果操作未完成,则函数的返回值为 0, 最后错误 函数返回 997。
线程可以通过以下两种方法之一管理重叠操作:

1.使用 操作结果 或 重叠结果 函数等待重叠操作完成。
如果使用 重叠结果 ,则调用线程可以为重叠操作指定超时,或执行可发出警报的等待。
2.在其中一个等待函数中指定 重叠类 结构的手动重置事件对象的句柄,然后在等待函数返回后调用操作结果或重叠结果。
函数返回已完成的重叠操作的结果,对于适合此类信息的函数,它将报告已传输的实际字节数。

在单个线程上同时执行多个重叠操作时,调用线程必须为每个操作指定 重叠类 结构。
每个 重叠类 结构必须指定
不同手动重置事件对象的句柄。
为了等待任何一个重叠的操作完成,线程会将所有手动重置事件句柄指定为其中一个多对象 等待函数中的等待条件。
多对象等待函数的返回值指示向哪个手动重置事件对象发出信号,以便线程可以确定哪个重叠操作导致等待操作完成。

对每个重叠操作使用单独的事件对象更安全,而不是不指定任何事件对象或将同一事件对象用于多个操作。
如果未在 重叠类 结构中
指定任何事件对象,则当重叠操作完成时,系统会向文件、命名管道或通信设备的状态发出信号。
因此,可以在等待函数中将这些句柄指定为同步对象,
尽管它们用于此目的可能难以管理,因为在同一文件、命名管道或通信设备上同时执行重叠操作时,
无法知道哪个操作导致对象状态被发出信号。

线程不应重复使用某个事件,前提是该事件仅由该线程的重叠操作发出信号。
事件在与正在完成的重叠操作相同的线程上发出信号。
在多个线程上使用相同的事件可能会导致争用条件,在该条件下,对于操作首先完成的线程,
对于使用该事件的其他线程,该事件会正确发出事件信号。
然后,在下一个重叠操作完成时,将针对使用该事件的所有线程再次向事件发出信号,依此进行,直到所有重叠操作完成。

有关说明如何使用重叠操作、完成例程和 操作结果 函数的示例,请参阅 命名管道。

Windows Vista、Windows Server 2003 和 Windows XP:
重用 重叠类 结构时要小心。
如果在多个线程上重复使用 重叠类 结构,并在 等待 参数设置为 真 的情况下调用 操作结果,
则调用线程必须确保在重用结构之前发出关联的事件信号。
这可以通过在调用 操作结果 后使用 等单对象 函数来强制线程等待操作完成。
请注意,事件对象必须是手动重置事件对象。
如果使用 自动重置事件对象,则调用将 等待 参数设置为 真 的 操作结果 会导致无限期阻止该函数。
对于在应用程序清单中将 Windows 7 指定为支持的操作系统的应用程序,
从 Windows 7 和 Windows Server 2008 R2 开始,此行为发生了变化。

异步过程调用

异步 过程调用 (APC) 是在特定线程的上下文中异步执行的函数。
当 APC 排队到线程时,系统会发出软件中断。 下次计划线程时,它将运行 APC 函数。
系统生成的 APC 称为 内核模式 APC。 应用程序生成的 APC 称为 用户模式 APC。
线程必须处于可警报状态才能运行用户模式 APC。

每个线程都有自己的APC队列。应用程序通过调用 用户异步 函数将APC排队到线程。
调用线程在对 用户异步 的调用中指定APC函数的地址。APC的队列是线程调用APC函数的请求。

当用户模式 APC 排队时,它排队的线程不会定向到调用 APC 函数,除非它处于可警报状态。
线程在调用 异步延时、对象等单、等列消息、等列对象 或 等待对象 函数时进入可警报状态。
如果在 APC 排队之前满足等待,则线程不再处于可警报等待状态,因此不会执行 APC 函数。
但是,APC 仍处于排队状态,因此当线程调用另一个可警报等待函数时,将执行 APC 函数。

读入文件、设置延时、指定延时 和 写入文件 函数使用 APC 作为完成通知回调机制来实现。
如果使用 线程池,请注意,APC 不与其他信号机制一样工作,因为系统控制线程池线程的生存期,
因此线程有可能在传递通知之前终止。
不要使用基于 APC 的信号机制(如 设置延时 或 指定延时 的 回调 参数),而是使用可等待的对象,
例如使用 新建计时 创建的计时器。
对于 I/O,请使用使用 新建进出 创建的 I/O 完成对象或基于事件的 重叠类 结构,其中事件可以传递给 设置等待 函数

同步内部
发出 I/O 请求时,将分配一个结构来表示请求。 此结构称为 I/O 请求数据包 (IRP)。
使用同步 I/O 时,线程生成 IRP,将其发送到设备堆栈,
并在内核中等待 IRP 完成。 使用异步 I/O,线程生成 IRP 并将其发送到设备堆栈。
堆栈可能会立即完成 IRP,也可能返回挂起状态,指示请求正在进行。
发生这种情况时,IRP 仍与线程关联,因此,如果线程终止或调用 取消操作 等函数,IRP 将被取消。
在此期间,线程可以继续执行其他任务,同时设备堆栈继续处理 IRP。

系统可通过多种方式指示 IRP 已完成:
使用操作的结果更新重叠结构,以便线程可以轮询以确定操作是否已完成。
向重叠结构中的事件发出信号,以便线程可以在事件上同步并在操作完成时被唤醒。
将 IRP 排队到线程的挂起的 APC,以便线程在进入可警报等待状态时执行 APC 例程,
并从等待操作返回,状态指示它执行了一个或多个 APC 例程。
将 IRP 排队到 I/O 完成端口,在该端口上等待的下一个线程将执行该端口。

在 I/O 完成端口上等待的线程不会处于可警报状态。
因此,如果这些线程向线程发出设置为作为 APC 完成的 IRP,
则这些 IPC 完成不会及时发生;仅当线程从 I/O 完成端口获取请求,然后碰巧进入可警报等待时,才会发生这些请求。

同步异步 ——相关函数
中文名称英文名称示例作用
Beep嘀(声音频率,持续时间)在扬声器上产生简单的音调,频率在37到32767之间,时间为毫秒数
重叠结果GetOverlappedResultEx重叠结果(文件,重叠类,@实传,超时,等待)检索指定文件、命名管道或通信设备上的重叠操作的结果。
创建信号CreateSemaphoreA创建信号(继承,初数,最大数,名称)创建或打开命名或未命名的信号灯对象。
创建事件CreateEventA事件=创建事件(属性,复位,状态,名称)创建一个事件,返回事件对象的句柄。
新建事件CreateEventExA事件=新建事件(安属,名称,标志,访问)创建一个事件,返回事件对象的句柄。标志:1手动重置,2已发信号
新建互斥CreateMutexExA新建互斥(安属,名称,标志,访问)创建或打开一个命名或未命名的互斥体对象。标志:1创建者所有
新建信号CreateSemaphoreExA新建信号(安属,初数,最大,名称,0,访问)创建或打开命名或未命名的信号灯对象。
内存通知CreateMemoryResourceNotification内存通知(条件)创建内存资源通知对象。条件:0内存不足,1内存较高
新建延时CreateWaitableTimerExA新建延时(安属,名称,标志,访问)创建或打开可等待的计时器对象。标志:1手动重置,2高分辨率
创建互斥CreateMutexA创建互斥(访问,继承,对象名)创建一个互斥体,可判断程序是否重复运行
关闭进出CloseThreadpoolIo关闭进出(进出)释放指定的I/O完成对象。
新建进出CreateThreadpoolIo新建进出(文件,回调,附加,回调环境)创建新的I/O完成对象。
开始进出StartThreadpoolIo开始进出(进出)通知线程池,I/O 操作可能会针对指定的 I/O 完成对象开始。
关闭等待CloseThreadpoolWait关闭等待(等待)释放指定的等待对象。
新建等待CreateThreadpoolWait新建等待(回调,附加,回调环境)创建新的等待器对象。
设置等待SetThreadpoolWait设置等待(等待,对象,超时)设置等待对象。超时为正值代表UTC绝对时间,负值表示相对时间(单位100 纳秒)
指定等待SetThreadpoolWaitEx指定等待(等待,对象,超时)设置等待对象。超时为正值代表UTC绝对时间,负值表示相对时间(单位100 纳秒)
关闭计时CloseThreadpoolTimer关闭计时(计时器)释放指定的计时器对象。
新建计时CreateThreadpoolTimer新建计时(回调,附加,回调环境)创建新的计时器对象。
是计时器IsThreadpoolTimerSet是计时器(计时器)确定当前是否设置了指定的计时器对象。
设置计时SetThreadpoolTimer设置计时(计时器,时间,周期,延时)设置计时器对象。时间为正值代表UTC绝对时间,负值表示相对时间(单位100 纳秒)
指定计时SetThreadpoolTimerEx指定计时(计时器,时间,周期,延时)设置计时器对象。时间为正值代表UTC绝对时间,负值表示相对时间(单位100 纳秒)
关闭工作CloseThreadpoolWork关闭工作(工作)释放指定的工作对象。
新建工作CreateThreadpoolWork新建工作(回调,附加,回调环境)创建新的工作器对象。
发布工作SubmitThreadpoolWork发布工作(工作)将工作对象发布到线程池。 工作线程调用工作对象的回调函数。
安号边符AddSIDToBoundaryDescriptor安号边符(边符,SID)将安全标识符 (SID) 添加到指定的边界描述符。
创建边符CreateBoundaryDescriptorA创建边符(名称,标志)创建边界描述符。标志:1无论生成者或使用者都要创建。
删除边符DeleteBoundaryDescriptor删除边符(边符)删除指定的边界描述符。
创建私名CreatePrivateNamespaceA创建私名(安属,隔离边字,前缀)创建专用命名空间。
打开私名OpenPrivateNamespaceA打开私名(隔离边字,前缀)打开专用命名空间。
关闭私名ClosePrivateNamespace关闭私名(命名空间,标志)关闭打开的命名空间句柄。标志:1销毁
取消延时CancelWaitableTimer取消延时(计时器)取消由指定文件的调用线程颁发的所有挂起输入和输出 (I/O) 操作。
创建延时CreateWaitableTimerA创建延时(计时结构,手动,名称)创建或打开可等待的计时器对象。
删除资源DeleteCriticalSection删除资源(对象)删除关键节对象释放由该对象使用的所有系统资源。
等关键节EnterCriticalSection等关键节(节对象)等待指定关键部分对象的所有权。此函数将在授予调用线程所有权时返回。
删除屏障DeleteSynchronizationBarrier删除屏障(屏障)删除同步屏障。
等待屏障EnterSynchronizationBarrier等待屏障(屏障,标志)导致调用线程在同步屏障处等待,直到最大线程数进入该屏障。
初始屏障InitializeSynchronizationBarrier初始屏障(@屏障,线程数,旋转数)初始化新的同步屏障。旋转数为-1,则线程旋转2000次。
初始条件InitializeConditionVariable初始条件(@条件变量)初始化条件变量。
初始化节InitializeCriticalSection初始化节(@关键节)初始化关键节对象。
初始节数InitializeCriticalSectionAndSpinCount初始节数(@关键节,计数)初始化关键节对象并设置关键节的旋转计数。
释放节权LeaveCriticalSection释放节权(@关键节)释放指定关键节对象的所有权。
进关键节TryEnterCriticalSection进关键节(关键节)尝试进入关键部分而不发生阻塞。如果调用成功,调用线程将获取关键部分的所有权。
原子比较InterlockedCompareExchange原子比较(@输入,更新,值)执行原子操作,将两个输入值进行比较。更新非零输入参数输出结果
原子递减InterlockedDecrement原子递减(@变量)将调用方提供的整数类型变量递减为原子操作。
原子更改InterlockedExchange原子更改(@变量,数值)将整数变量设置为作为原子操作的给定值。
原子添加InterlockedExchangeAdd原子添加(@变量,数值)将值作为原子操作添加到给定整数中,并返回给定整数的原始值。
原子递增InterlockedIncrement原子递增(@变量)递增调用方提供的变量作为原子操作。
内存可用IsBadCodePtr内存可用(内存)确定调用进程是否具有对指定地址的内存的读取访问权限。
内存字串IsBadStringPtrA内存字串(内存)验证调用进程是否对指定的内存范围具有读取访问权限。
一次初始InitOnceComplete一次初始(@一次)初始化一次性初始化结构。
一次开始InitOnceBeginInitialize一次开始(一次,标志,@状态,@数据)开始一次性初始化。标志:0初始化,1只查状态,2允许多次初始化
一次完成InitOnceComplete一次完成(一次,标志,数据)完成一次性初始化。标志:2异步模式,4尝试失败
一次执行InitOnceExecuteOnce一次执行(一次,回调,附加,@数据)当多个线程调用同一个此函数时,只有一个线程将执行回调函数。其余线程将阻塞,直到回调函数完成。
打开互斥OpenMutexA打开互斥(访问,继承,对象名)打开一个互斥体,可判断程序是否重复运行
打开信号OpenSemaphoreA打开信号(访问,继承,信号名)打开现有的命名信号灯对象。
精确计数QueryPerformanceCounter精确计数(文件时间类)检索性能计数器的当前值,这是一个高分辨率 (小于1us) 时间戳,可用于时间间隔度量。
计数频率QueryPerformanceFrequency计数频率(文件时间类)检索性能计数器的频率。性能计数器的频率在系统启动时固定,并且在所有处理器中保持一致。
释放互斥ReleaseMutex释放互斥(对象)释放指定的互斥对象的所有权
信号增量ReleaseSemaphore信号增量(对象)按指定量增加指定的信号灯对象的计数。
打开延时OpenWaitableTimerA打开延时(访表,继承,名称)打开现有的命名可等待计时器对象。
打开事件OpenEventA打开事件(访问,继承,事件名)$1F0003全权访问,2允许修改和重置事件,$100000允许事件同步
脉冲事件PulseEvent脉冲事件(事件)发出脉冲信号释放等待线程,无信号后将其重置
重置事件ResetEvent重置事件(事件)将指定的事件对象设置为非信号状态
修改事件SetEvent修改事件(事件)将指定的事件对象的状态设置为发信号
列线程池RegisterWaitForSingleObject列线程池(等待,对象,回调,附加,超时,标志)指示线程池中的等待线程等待对象。发出信号或超时等待线程会将指定的回调函数排队到线程池
取消等待UnregisterWait取消等待(等待)取消 列线程池 函数发出的已注册等待操作。
注销等待UnregisterWaitEx注销等待(等待,事件)取消 列线程池 函数发出的已注册等待操作。
延时Sleep延时(毫秒)暂停执行当前线程指定的毫秒数
异步延时SleepEx异步延时(毫秒,异步)挂起当前线程,直到满足指定条件。
对象等单SignalObjectAndWait对象等单(对象,等对象,毫秒,排队)向一个对象发出信号,并等待另一个对象作为单个操作。排队为假不返回无回调
等多对象WaitForMultipleObjects等多对象(对象数,对象组,等所有,超时)等待一个或所有指定的对象处于信号状态或超时间隔已过。
等列对象WaitForMultipleObjectsEx等列对象(对象数,对象组,等所有,超时,排队)等待一个或所有指定的对象处于信号状态、I/O 完成例程或异步过程调用 (APC) 排队到线程,或超时间隔已过。
等单对象WaitForSingleObject等单对象(对象,毫秒)等待指定的对象处于信号状态或超时间隔已过。
等待对象WaitForSingleObjectEx等待对象(对象,毫秒,排队)等待指定的对象处于信号状态、I/O 完成例程或异步过程调用 (APC) 排队到线程,或超时间隔已过。
设置延时SetWaitableTimer设置延时(计时,时间,周期,回调,附加,还原)激活指定的可等待计时器。时间为正值代表UTC绝对时间,负值表示相对时间(单位100 纳秒)。周期为毫秒。还原为真可唤醒节能模式。
指定延时SetWaitableTimerEx指定延时(计时,时间,周期,回调,附加,请求,延时)激活指定的可等待计时器。时间为正值代表UTC绝对时间,负值表示相对时间(单位100 纳秒)。周期和延时为毫秒。

进出回调
中文名字英文名称参数作用解释
进出回调IoCompletionCallback6如果应用程序启动 I/O 完成对象的工作线程,则实现此回调。
进出回调 参数表
中文英文类型作用解释
实例Instance整数定义回调实例的TP_CALLBACK_INSTANCE结构。应用程序不会修改此结构的成员。
附加Context整数应用程序定义的数据。
重叠Overlapped整数重叠类
结果IoResult整数I/O 操作的结果。如果 I/O 成功,则此参数为0。否则,此参数是系统错误代码之一。
字数NumberOfBytesTransferred整数在已完成的 I/O 操作期间传输的字节数。
进出Io整数一个TP_IO结构,用于定义生成回调的 I/O 完成对象。

计时回调
中文名字英文名称参数作用解释
计时回调Ptimerapcroutine3应用程序定义的计时器完成例程。
计时回调 参数表
中文英文类型作用解释
附加lpArgToCompletionRoutine整数传递给回调函数的附加参数。
低时dwTimerLowValue整数发出计时器信号的基于 UTC 的时间的低序部分。
高时dwTimerHighValue整数计时器发出信号的基于 UTC 的时间的高阶部分。

工作回调
中文名字英文名称参数作用解释
工作回调WorkCallback3应用程序启动工作对象的工作线程,则实现此回调。
工作回调 参数表
中文英文类型作用解释
实例Instance整数定义回调实例的TP_CALLBACK_INSTANCE结构。应用程序不会修改此结构的成员。
附加Context整数应用程序定义的数据。
工作Work整数一个TP_WORK结构,用于定义生成回调的工作对象。

等待回调
中文名字英文名称参数作用解释
等待回调WorkCallback4应用程序启动工作对象的工作线程,则实现此回调。
等待回调 参数表
中文英文类型作用解释
实例Instance整数定义回调实例的TP_CALLBACK_INSTANCE结构。应用程序不会修改此结构的成员。
附加Context整数应用程序定义的数据。
等待Wait整数一个TP_WAIT结构,用于定义生成回调的等待对象。
结果WaitResult整数等待操作的结果。0结果对象,0x102超时

超时回调
中文名字英文名称参数作用解释
超时回调WaitOrTimerCallback3应用程序定义的函数,用作计时器回调或已注册等待回调的起始地址。
超时回调 参数表
中文英文类型作用解释
附加lpParameter整数传递给回调函数的线程数据。
超时TimerOrWaitFired整数如果此参数为 TRUE,则等待超时。如果此参数为 FALSE,则表示已发出等待事件信号。(对于计时器回调,此参数始终为 TRUE。

异步回调
中文名字英文名称参数作用解释
异步回调APCProc1应用程序定义的完成例程。
异步回调 参数表
中文英文类型作用解释
附加Parameter整数传递给回调函数的可选参数。

一次回调
中文名字英文名称参数作用解释
一次回调InitOnceCallback3返回真,则块标记为已初始化。
一次回调 参数表
中文英文类型作用解释
一次InitOnce整数指向一次性初始化结构的指针。
附加Parameter整数传递给回调函数的可选参数。
数据Context整数要使用一次性初始化结构存储的数据。

电源请求类
中文名字英文名称长度作用解释
电源请求类REASON_CONTEXT16包含有关电源请求的信息。
电源请求类 成员表
中文英文类型作用解释
版本Version整数结构的版本号。此参数必须设置为 0。
格式Flags整数电源请求原因的格式。1=包含一个简单的不可本地化字符串,2标识可本地化的字符串资源
本地Reason.Detailed整数用于标识可本地化的字符串资源,用于描述电源请求的原因。
Reason.Detailed.LocalizedReasonModule包含字符串资源的模块。
Reason.Detailed.LocalizedReasonId字符串资源的 ID。
Reason.Detailed.ReasonStringCount ReasonStrings 参数中的字符串数。
Reason.Detailed.ReasonStrings运行时字符串资源中要替换的字符串数组。
非本Reason.SimpleReasonString整数描述电源请求原因的非本地化字符串。

线程池回调标志
英文名称参数作用解释
WT_EXECUTEDEFAULT0x00000000默认情况下,回调函数将排队到非 I/O 工作线程。
WT_EXECUTEINIOTHREAD0x00000001未使用此标志。
WT_EXECUTEINPERSISTENTTHREAD0x00000080回调函数将排队到永不终止的线程。 它不保证每次都使用相同的线程。 此标志应仅用于短任务,否则可能会影响其他等待操作。
WT_EXECUTEINWAITTHREAD0x00000004回调函数由等待线程本身调用。 此标志应仅用于短任务,否则可能会影响其他等待操作。
WT_EXECUTELONGFUNCTION0x00000010回调函数可以执行长时间的等待。 此标志可帮助系统确定是否应创建新线程。
WT_EXECUTEONLYONCE0x00000008调用回调函数一次后,线程将不再等待句柄。 否则,每次等待操作完成时,计时器都会重置,直到取消等待操作。
WT_TRANSFER_IMPERSONATION0x00000100回调函数将使用当前访问令牌,无论是进程令牌还是模拟令牌。 如果未指定此标志,则回调函数仅使用进程令牌执行。

同步屏障阻塞
英文名称参数作用解释
SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY1指定进入屏障的线程应立即阻塞,直到最后一个线程进入屏障。。
SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY2指定进入屏障的线程应旋转,直到最后一个线程进入屏障,即使旋转线程超过屏障的最大旋转计数。
SYNCHRONIZATION_BARRIER_FLAGS_NO_DELETE4指定函数可以跳过所需的工作,以确保安全删除屏障,从而提高性能。仅当永远不会删除屏障时,才应使用此标志。