You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决WriteFileEx不调用完成例程的问题?HID设备异步写入异常

问题分析与解决方案

核心问题

WriteFileEx 的完成例程必须在线程进入可警告等待状态(Alertable Wait)时才会被系统触发。你的代码里虽然调用了 WriteFileEx 且返回成功,但如果当前线程没有调用支持可警告等待的函数(比如带Ex后缀的等待/睡眠函数,且最后一个参数设为TRUE),系统根本没机会执行你的完成例程,自然无法释放OVERLAPPED结构。

具体修复方案

  1. 让线程进入可警告等待状态
    如果你是在DirectInput的回调线程里执行的WriteFileEx,得确保这个线程后续会进入可警告等待。比如如果是消息循环线程,修改消息循环:

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        // 插入可警告等待,给系统触发完成例程的机会
        MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, MWMO_ALERTABLE);
    }
    

    如果是工作线程,空闲时用SleepEx(INFINITE, TRUE)替代普通Sleep或非Ex版本的等待函数。

  2. 确认OVERLAPPED结构的有效性
    你初始化OVERLAPPED{0}没问题,但要注意这个结构必须在完成例程执行前保持存在——目前你动态分配的方式是对的,但只要完成例程不触发就会内存泄漏,这也是必须解决完成例程调用问题的原因。

  3. 备选:用GetOverlappedResultEx主动查询(临时排查)
    如果暂时没法修改线程等待逻辑,可以用GetOverlappedResultEx主动等待异步操作完成,同时触发完成例程:

    DWORD bytesWritten;
    if (GetOverlappedResultEx(my_hid, over, &bytesWritten, INFINITE, TRUE))
    {
        // 操作完成,这里也能手动释放OVERLAPPED
        delete over;
    }
    

    但这只是临时方案,长期来看还是要让完成例程自动触发。

额外建议

如果修改线程等待逻辑有困难(比如不想影响游戏主线程的运行),可以考虑改用**IOCP(完成端口)**处理异步HID写入。IOCP的完成通知不依赖线程的可警告等待,更适合这种被第三方框架(DirectInput)托管线程的场景。

内容的提问来源于stack exchange,提问作者ElSnowman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 02:35:17