当前位置: 首页 > news >正文

网站更换域名备案服务管理系统

网站更换域名备案,服务管理系统,在线平面设计作图网站,乐山建设企业网站文章目录WaitForSingleObject函数详解核心概念函数原型参数详解返回值工作流程图解一个简单的代码示例 (C)总结与要点当第二个参数是 INFINITE 时,如何以及为何要判断返回值是否等于 WAIT_FAILED?核心结论为什么 INFINITE 情况下还会失败?流程…

文章目录

    • WaitForSingleObject函数详解
      • 核心概念
      • 函数原型
      • 参数详解
      • 返回值
      • 工作流程图解
      • 一个简单的代码示例 (C++)
      • 总结与要点
    • 当第二个参数是 INFINITE 时,如何以及为何要判断返回值是否等于 WAIT_FAILED?
      • 核心结论
      • 为什么 INFINITE 情况下还会失败?
      • 流程图:INFINITE 模式的执行逻辑
      • 正确的代码实践
      • 一个具体的错误场景示例
      • 总结

WaitForSingleObject函数详解

核心概念

WaitForSingleObject 是一个用于线程同步的核心函数。它的作用很简单:让一个线程等待,直到某个特定的“对象”达到“已通知”的状态,或者超过指定的等待时间。

你可以把它想象成:

  • 你在等一个朋友(对象)打电话(变为已通知状态)给你。
  • 你决定最多等30分钟(超时时间)。
  • 结果有两种:要么他在30分钟内打来了(对象已通知),要么30分钟到了他还没打(超时)。

函数原型

DWORD WaitForSingleObject([in] HANDLE hHandle,        // 要等待的对象的句柄[in] DWORD  dwMilliseconds  // 超时时间,以毫秒为单位
);

参数详解

  1. hHandle [输入参数]

    • 这是你要等待的内核对象的句柄。
    • 这个对象必须是一个可以“被等待”的同步对象。常见的包括:
      • 线程 (Thread): 等待线程执行结束。线程结束时变为已通知状态。
      • 进程 (Process): 等待进程执行结束。进程结束时变为已通知状态。
      • 互斥量 (Mutex): 等待获取该互斥量的所有权。当其他线程释放互斥量时,它变为已通知状态。
      • 事件 (Event): 等待事件被“触发”。另一个线程可以调用 SetEvent 来手动将其设置为已通知状态。
      • 信号量 (Semaphore): 等待信号量的计数大于0。当计数大于0时,它为已通知状态。
  2. dwMilliseconds [输入参数]

    • 超时时间,单位是毫秒(milliseconds)。
    • 如果这个参数设置为 0,函数会立即测试对象的状态并立即返回,而不会真正地阻塞线程。
    • 如果这个参数设置为 INFINITE(一个定义为0xFFFFFFFF的常量),函数会无限期地等待,直到对象变为已通知状态。这是一个阻塞调用,需要谨慎使用,以免造成程序死锁。

返回值

函数的返回值告诉你等待的结果,它是一个 DWORD 类型的值。

  • WAIT_OBJECT_0 (值为 0)

    • 等待成功! 这表示你等待的对象已经变成了“已通知”状态。你的线程现在可以继续执行后续任务了(例如,获取互斥锁、处理线程结束后的资源清理等)。
  • WAIT_TIMEOUT (值为 258)

    • 等待超时。 在指定的 dwMilliseconds 时间过后,对象仍然没有变成“已通知”状态。线程会从等待中唤醒并继续执行。
  • WAIT_ABANDONED (值为 0x80)

    • 这是一个特殊情况,主要针对互斥量 (Mutex)。 它表示你等待的互斥量被另一个线程在结束时遗弃了(即该线程在释放互斥量之前就终止了)。虽然你仍然能获取到这个互斥量,但可能意味着受保护的共享数据处于不确定状态,需要特别小心处理。
    • 对于其他对象,不会返回这个值。
  • WAIT_FAILED (值为 (DWORD)0xFFFFFFFF)

    • 函数调用失败。 例如,你传入了一个无效的句柄。此时可以调用 GetLastError() 来获取具体的错误信息。

工作流程图解

下图直观地展示了 WaitForSingleObject 的工作逻辑:

dwMilliseconds = 0
dwMilliseconds = INFINITE
设置了具体时间
调用 WaitForSingleObject
对象是否已 signaled?
立即返回 WAIT_OBJECT_0
设置超时时间?
立即返回 WAIT_TIMEOUT
无限期阻塞等待
阻塞等待指定时间
对象变为 signaled?
返回 WAIT_OBJECT_0
在时间内对象变为 signaled?
返回 WAIT_TIMEOUT

一个简单的代码示例 (C++)

以下示例演示了如何使用 WaitForSingleObject 来等待一个子线程结束。

#include <windows.h>
#include <iostream>// 简单的线程函数
DWORD WINAPI MyThreadFunction(LPVOID lpParam) {std::cout << "子线程开始工作,模拟耗时3秒..." << std::endl;Sleep(3000); // 模拟工作,睡眠3秒std::cout << "子线程工作完成!" << std::endl;return 0;
}int main() {// 创建一个子线程HANDLE hThread = CreateThread(NULL,                   // 默认安全属性0,                      // 默认栈大小MyThreadFunction,       // 线程函数NULL,                   // 传递给线程函数的参数0,                      // 默认创建标志NULL                    // 不需要获取线程ID);if (hThread == NULL) {std::cerr << "创建线程失败!" << std::endl;return 1;}std::cout << "主线程正在等待子线程结束,最多等5秒..." << std::endl;// 主线程在这里等待子线程结束,最多等待5000毫秒(5秒)DWORD dwWaitResult = WaitForSingleObject(hThread, 5000);// 根据返回值判断发生了什么switch (dwWaitResult) {case WAIT_OBJECT_0:std::cout << "成功:子线程已正常结束。" << std::endl;break;case WAIT_TIMEOUT:std::cout << "警告:等待超时,子线程仍在运行。" << std::endl;break;case WAIT_FAILED:std::cout << "错误:WaitForSingleObject 调用失败。" << std::endl;break;// 对于线程,不会返回 WAIT_ABANDONED}// 不要忘记关闭内核对象句柄CloseHandle(hThread);std::cout << "主程序退出。" << std::endl;return 0;
}

可能的输出:

  1. 子线程在5秒内结束:输出 "成功:子线程已正常结束。"
  2. 子线程运行超过5秒:输出 "警告:等待超时,子线程仍在运行。"

总结与要点

  • 目的WaitForSingleObject 是用于线程同步,让一个线程暂停运行,等待某个条件(对象变为已通知)被满足。
  • 核心参数:一个对象句柄和一个超时时间
  • 核心返回值WAIT_OBJECT_0(成功),WAIT_TIMEOUT(超时),WAIT_ABANDONED(互斥量被遗弃)。
  • 常见用途
    • 等待创建的线程或进程结束,以便进行资源清理。
    • 等待获取一个同步对象(如互斥量、信号量)的所有权,以实现对共享资源的互斥访问。
    • 等待一个事件被触发,以协调多个线程的执行顺序。
  • 重要提醒:始终检查返回值,并根据不同的返回值进行相应的处理。特别是使用 INFINITE 时要小心死锁风险。使用后记得用 CloseHandle 关闭句柄。
    好的,这是一个非常重要且常见的场景。我们来详细解释当第二个参数是 INFINITE 时,如何以及为何要判断返回值是否等于 WAIT_FAILED

当第二个参数是 INFINITE 时,如何以及为何要判断返回值是否等于 WAIT_FAILED?

核心结论

即使你将超时时间设置为 INFINITE(无限等待),函数仍然有可能因为错误而立即返回 WAIT_FAILED INFINITE 只保证函数在“没有错误发生”的情况下会一直等待对象,但它不能防止其他错误导致函数失败。

因此,在任何情况下,包括使用 INFINITE 时,都必须检查返回值是否为 WAIT_FAILED,这是健壮编程的基本要求。


为什么 INFINITE 情况下还会失败?

INFINITE 参数的含义是:“如果一切正常,就一直等下去,直到对象变为已通知状态”。
但它无法避免以下几种会导致函数执行失败(返回 WAIT_FAILED) 的情况:

  1. 无效的句柄 (Most Common)

    • 你传入的 hHandle 不是一个有效的、可以等待的内核对象句柄。
    • 例如:句柄为 NULL、句柄已经用 CloseHandle 关闭了、或者句柄根本就不是一个同步对象(比如是一个文件句柄)。
  2. 权限不足

    • 当前线程没有足够的权限来等待这个对象。这在跨进程等待时可能发生。
  3. 意外的系统错误

    • 极少数情况下,系统内部发生错误,导致等待操作无法进行。

流程图:INFINITE 模式的执行逻辑

下图清晰地展示了即使设置为无限等待,也必须在开始时进行有效性检查,并最终处理失败情况:

对象变为已通知
等待过程中出现系统级错误
调用 WaitForSingleObject
hHandle, INFINITE
句柄有效且有权等待?
立即返回 WAIT_FAILED
进入无限期阻塞等待状态
等待期间发生什么?
返回 WAIT_OBJECT_0
返回 WAIT_FAILED
必须检查并处理错误
按成功处理

从流程图可以看出,WAIT_FAILED 可能在两个阶段返回:

  1. 初始检查阶段:参数无效,函数根本不会开始等待。
  2. 等待过程中:极其罕见的情况下系统出错。

正确的代码实践

你必须先检查是否失败,然后再去判断是否是成功的等待。

HANDLE hThread = CreateThread(...); // 获取一个需要等待的句柄// 使用 INFINITE 等待
DWORD dwWaitResult = WaitForSingleObject(hThread, INFINITE);// 第一优先:检查是否调用失败
if (dwWaitResult == WAIT_FAILED) {// 调用 GetLastError 获取详细的错误代码DWORD dwError = GetLastError();// 进行错误处理,例如打印日志、清理资源、安全退出等printf("WaitForSingleObject failed! Error code: %d\n", dwError);CloseHandle(hThread);return -1;
}// 第二优先:检查是否成功等待(只有在没有失败的情况下才做这个判断)
if (dwWaitResult == WAIT_OBJECT_0) {// 等待成功,对象已通知printf("Thread exited successfully.\n");
}
// 注意:因为参数是INFINITE,所以绝对不会返回WAIT_TIMEOUT
// 对于线程句柄,也绝对不会返回WAIT_ABANDONED// ... 其他处理 ...
CloseHandle(hThread);

一个具体的错误场景示例

HANDLE hInvalidHandle = (HANDLE)12345; // 这是一个完全瞎编的无效句柄// 即使使用 INFINITE,这个调用也会立即返回 WAIT_FAILED
// 因为它无法等待一个不存在的对象
DWORD dwResult = WaitForSingleObject(hInvalidHandle, INFINITE);if (dwResult == WAIT_FAILED) {DWORD err = GetLastError();// 这里 err 很可能是 6 (ERROR_INVALID_HANDLE)printf("Failed as expected. Error: %d\n", err);
}

总结

  1. INFINITE 不代表“永不返回”:它只代表“在无错误情况下,为等待一个有效的对象而永不返回”。
  2. 错误处理优先:返回值检查的顺序应该是 WAIT_FAILED,再 WAIT_OBJECT_0,最后是其他状态。
  3. 必须检查 WAIT_FAILED:忽略这个检查意味着你的代码无法处理无效输入或意外情况,会导致程序在发生错误时行为不可预测(甚至崩溃)。
  4. 使用 GetLastError():一旦确认返回 WAIT_FAILED,立即调用 GetLastError() 来诊断具体原因,这是调试和错误处理的关键步骤。

所以,无论第二个参数是什么,判断是否等于 WAIT_FAILED 都是必不可少的一步。

http://www.dtcms.com/a/487959.html

相关文章:

  • 【Frida Android】基础篇8:Java层Hook基础——调用带对象参数的方法
  • 网站空间一年多少钱应聘ui设计师自我介绍
  • 免费自己制作网站教程以下不属于专用网页制作工具的是
  • 做墙绘一般在哪个网站美橙互联网站备案平台
  • 青岛网站设计哪家公司企业展厅设计公司价格表
  • 做自媒体怎么在其它网站搬运内容竞价推广是什么意思
  • 做一个15页的网站怎么做在vs2010里怎么做网站
  • 上海网站建设微信开发wordpress手机版刷新
  • kubeasz部署过程记录
  • 力扣面试经典150题,第7(lc121),8(lc122),9(lc55),10(lc45)题
  • 网页设计素材有两种分别是什么vueseo解决方案
  • LoRA微调
  • 网站建设咨询服务商上海网站推广珈维
  • 青岛cms建站系统顺德门户网站建设公司
  • 【评测】百炼大模型视频生成初体验
  • 算法---动态规划(Dynamic Programming, DP)
  • 如何建立网站会员系统吗电商网站怎么做seo
  • 西安SEO网站推广长治网站制作
  • 山东城建建设职业学院教务网站第一章 网站建设基本概述
  • 新网站多久被收录自己做的网站搜索不到
  • 算法入门:专题二---滑动窗口(长度最小的子数组)类型题目攻克!
  • 知名排版网站wordpress如何安裝
  • 电子商务网站设计毕业设计论文电影网站开发PPT模板
  • index.html网站怎么做wordpress关注公众号发送验证码
  • dede做的网站打不开云服务器一般多少钱
  • HTTP Error 5OO.0- ASPNET Core lIS hosting failure (in-process)
  • 机械做卖产品网站百度识图网页版
  • 公司注册网站系统东营区住房和城乡建设局网站
  • LongCat-Flash:如何使用 SGLang 部署美团 Agentic 模型
  • 怎么让网站绑定域名访问不了开发软件怎么申请版权