excel - 在 VBA 中使用 Waitable Timer 对象 - 无效句柄错误
问题描述
我正在尝试在 VBA 中使用 Waitable Timer 对象,因为我想以低于 1 秒的延迟(所以没有Application.OnTime
)和参数(所以没有SetTimer
API)异步调用某些东西
我还没有发现有人在其他任何地方尝试过这个,所以我不得不从头开始,但我认为这应该是可行的。以下是 API 声明:
Public Declare Function CreateWaitableTimer Lib "kernel32" Alias "CreateWaitableTimerA" ( _
ByVal lpTimerAttributes As Long, _
ByVal manualReset As Boolean, _
ByVal lpTimerName As Long) As Long
'The A meaning Ansi not Unicode https://jeffpar.github.io/kbarchive/kb/145/Q145727/
Public Declare Function SetWaitableTimer Lib "kernel32" ( _
timerHandle As Long, _
lpDueTime As fileTime, _
lPeriod As Long, _
pfnCompletionRoutine As Long, _
lpArgToCompletionRoutine As Long, _
fResume As Boolean) As Boolean
其中引用了一个文件时间(结构)
'see https://social.msdn.microsoft.com/Forums/sqlserver/en-US/a28a32c6-df4e-41b9-94ce-6260812dd92f/problem-trying-to-run-32-bit-vba-program-on-a-64-bit-machine?forum=exceldev
Public Type fileTime
dwLowDateTime As Long
dwHighDateTime As Long
End Type
我这样调用 API:
'[...]
args = 1234 'public args As Long so it doesn't go out of scope while the timer is waiting
Dim timerHandle As Long
timerHandle = CreateWaitableTimer(0, False, 0)
Debug.Print GetSystemErrorMessageText(Err.LastDllError)
If Not SetWaitableTimer(timerHandle, absoluteDueTime, 0, AddressOf TimerCallbacks.pointerProc, VarPtr(args), False) Then
Debug.Print "Error: "; GetSystemErrorMessageText(Err.LastDllError)
End If
GetSystemErrorMessageText来自 Chip Pearson。absoluteDueTime
是一个变量,在过程中提前1 秒fileTime
设置为Now + 1 秒。我进入即时窗口:
0 - 操作成功完成。
错误:6 - 句柄无效。
这意味着CreateWaitableTimer
似乎有效但SetWaitableTimer
无效。
FWIWTimerCallbacks.pointerProc
看起来像:
Public Sub pointerProc(ByVal argPtr As Long, ByVal timerLowValue As Long, ByVal timerHighValue As Long)
Debug.Print "pointerProc called"; Time
End Sub
(但我认为这不是错误所在......)
解决方案
哦,问题出在所有内容的隐式 byRef 上:
Public Declare Function SetWaitableTimer Lib "kernel32" ( _
timerHandle As Long, _
lpDueTime As fileTime, _
lPeriod As Long, _
pfnCompletionRoutine As Long, _
lpArgToCompletionRoutine As Long, _
fResume As Boolean) As Boolean
指针必须通过 byVal 还是立即被尊重?这个对吗:
Public Declare Function SetWaitableTimer Lib "kernel32" ( _
byVal timerHandle As Long, _
byRef lpDueTime As fileTime, _
byRef lPeriod As Long, _
byVal pfnCompletionRoutine As Long, _
byVal lpArgToCompletionRoutine As Long, _
byRef fResume As Boolean) As Boolean
不确定是否所有的byRef
s 都是必要的
推荐阅读
- cypress - 出现错误 mochawesome-merge 错误:未知选项:--reportDir
- javascript - 我怎样才能让我的材料底部标签可见?
- swiftui - SwiftUI TabView 更多选项卡内容未显示
- excel - RemoveDuplicates 命令在共享工作簿中导致 1004 运行时错误(在非共享中工作)
- alloy - 使用合金的锁和钥匙问题解决方案
- javascript - 如何使我的导航栏浮动并使用 Bootstrap 4 分隔列表
- android - 将本机上传图像反应到 api 得到网络错误
- prolog - 定义一个关系 first_last(L1, L2),它接受一个列表 L1 并返回一个包含 L1 的前三个和后三个元素的列表 L2
- javascript - API正在使用CORS,如何在vue中使用axios?
- javascript - 按列过滤数据表以获取范围内的结果(单击按钮)