详细介绍WaitForSingleObject()

书籍:《Visual C++ 2017从入门到精通》的2.3.8 Win32控件编程

环境:visual studio 2022

WaitForSingleObject() 是 Windows API 中用于同步操作的核心函数,主要用于等待一个内核对象(如线程、进程、事件、互斥量等)进入有信号状态(Signaled)。以下是其详细解析:


​一、函数原型​
DWORD WaitForSingleObject(
    HANDLE hHandle,        // 内核对象句柄
    DWORD dwMilliseconds   // 等待时间(毫秒)
);

​二、参数说明​
  1. hHandle

    • ​类型​​:HANDLE
    • ​含义​​:指向目标内核对象的句柄。
    • ​有效对象类型​​:
      • 线程(Thread)
      • 进程(Process)
      • 事件(Event)
      • 互斥量(Mutex)
      • 信号量(Semaphore)
    • ​权限要求​​:句柄必须具有 SYNCHRONIZE 访问权限,否则函数调用失败。
  2. dwMilliseconds

    • ​类型​​:DWORD(32 位无符号整数)
    • ​取值​​:
      • INFINITE(0xFFFFFFFF):无限等待,直到对象变为有信号状态。
      • 0立即返回当前对象状态,不阻塞线程。
      • 其他正整数:等待的毫秒数(如 5000 表示等待 5 秒)。

​三、返回值​

函数返回一个 DWORD 类型的状态码,表示等待结果:

​返回值​​含义​
WAIT_OBJECT_0 (0x0)对象变为有信号状态。
WAIT_TIMEOUT (0x102)等待超时(仅在 dwMilliseconds 非 INFINITE 时发生)。
WAIT_FAILED (0xFFFFFFFF)函数调用失败,需通过 GetLastError() 获取错误码(如无效句柄、权限不足)。

​四、典型应用场景​
  1. 等待线程结束​
    主线程通过等待子线程句柄变为有信号状态,确保子线程完成任务后再继续执行:

    HANDLE hThread = CreateThread(...);
    WaitForSingleObject(hThread, INFINITE); // 无限等待子线程结束
    CloseHandle(hThread);
  2. ​事件驱动编程​
    等待事件对象被触发(如用户输入、数据到达):

    HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    // 其他线程触发事件:SetEvent(hEvent);
    DWORD result = WaitForSingleObject(hEvent, 5000); // 最多等待5秒
    if (result == WAIT_OBJECT_0) {
        // 事件触发,执行操作
    }
  3. ​互斥量同步​
    等待互斥量可用(避免资源竞争):

    HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
    WaitForSingleObject(hMutex, INFINITE); // 等待互斥量释放
    // 访问共享资源
    ReleaseMutex(hMutex);

​五、关键注意事项​
  1. ​句柄有效性​

    • 若 hHandle 无效(如已关闭或从未创建),函数返回 WAIT_FAILED
    • 需确保句柄具有 SYNCHRONIZE 权限。
  2. ​对象状态重置​

    • ​自动重置事件(AutoResetEvent)​​:当一个等待线程被唤醒后,对象自动变为无信号状态。
    • ​手动重置事件(ManualResetEvent)​​:需显式调用 ResetEvent() 重置状态。
  3. ​线程阻塞与CPU占用​

    • 等待期间线程处于挂起状态,不占用 CPU 资源。
    • 避免在 UI 线程中无限等待(如 INFINITE),可能导致界面假死。
  4. ​超时机制​

    • 合理设置超时时间,防止永久阻塞。
    • 超时后需检查对象状态(如通过 WaitForSingleObject 再次检测)。

​六、错误处理​

若函数返回 WAIT_FAILED,可通过 GetLastError() 获取错误码:

DWORD result = WaitForSingleObject(hHandle, 1000);
if (result == WAIT_FAILED) {
    DWORD err = GetLastError();
    printf("WaitForSingleObject failed: %lu\n", err);
}

常见错误码:

  • ERROR_INVALID_HANDLE (6):句柄无效。
  • ERROR_ACCESS_DENIED (5):权限不足。

​七、与其他函数对比​
​函数​​功能​​适用场景​
WaitForSingleObject等待单个内核对象变为有信号状态单一同步对象(如线程、事件)
WaitForMultipleObjects等待多个内核对象中的任意一个或全部变为有信号多路复用同步(如同时等待事件和信号量)

​八、代码示例​
#include <windows.h>
#include <stdio.h>

int main() {
    HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // 手动重置事件
    if (hEvent == NULL) {
        printf("CreateEvent failed: %lu\n", GetLastError());
        return 1;
    }

    // 模拟异步操作(如后台任务)
    printf("Waiting for event...\n");
    DWORD result = WaitForSingleObject(hEvent, 3000); // 等待3秒
    switch (result) {
        case WAIT_OBJECT_0:
            printf("Event triggered!\n");
            break;
        case WAIT_TIMEOUT:
            printf("Timeout: Event not triggered.\n");
            break;
        case WAIT_FAILED:
            printf("Error occurred.\n");
            break;
    }

    CloseHandle(hEvent);
    return 0;
}

​九、总结​

WaitForSingleObject() 是 Windows 同步编程的基础函数,通过阻塞线程直到目标内核对象变为有信号状态,实现线程间协调。
​核心要点​​:

  1. 确保句柄有效且具有同步权限。
  2. 合理设置超时时间,避免无限阻塞。
  3. 根据对象类型(事件、互斥量等)正确处理状态重置。
  4. 结合错误处理提升代码健壮性。

通过合理使用该函数,可以构建高效、可靠的多线程和异步应用程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值