我想澄清我对Excel的VBA Application.OnTime调度程序在调用其分配的过程时的操作的理解。特别是,如果在下一个计划的OnTime时间的3秒内,用户单击运行子例程的UserForm按钮,则我希望该子例程等待OnTime的过程开始,然后继续等待直到该过程结束,然后再继续它自己的活动(以避免冲突,两个例程可以访问相同的文件,等等)。如果用户在3s间隔之前单击一个按钮,则计划的计时器将被简单地取消,然后再重新计划。
我相信VBA不支持多线程,因此我认为OnTime调度程序必须与所有其他UserForm和Module例程在同一VBA线程单元中运行其分配的过程。从某些测试中可以看出,分配的OnTime过程在被触发时具有优先权,从而冻结了当时可能已经在运行的任何其他子例程的执行。
以下尝试似乎可行。请参阅其中的一些注释,以了解可能发生的情况。
Public NextCallTime As Date ' (Set as OnTime time for next scheduled procedure)
Public TimerRunning As Boolean ' (True when OnTime's procedure has been scheduled, False when procedure finishes)
...
Public Sub WaitForTimerTaskComplete()
Dim CurrentCallTime As Date
CurrentCallTime = NextCallTime ' Make a local copy to 'freeze' the applicable time value
'(because 'NextCallTime' could be updated by the time this Sub unfreezes to finish waiting)
' Wait until timer task commences, if within 3s from now...
If TimerRunning And DateDiff("s", Now(), CurrentCallTime) < 3 Then
' Loop into the frozen state induced by the timer task...
While DateDiff("s", Now(), CurrentCallTime) > -2: DoEvents: Wend
' [I use -2 as a 2-second overlap to ensure that the task has started (not guaranteed though)]
' Then continue to wait until timer task has finished, which updates 'NextCallTime'
' via a subsequent OnTime call [This line is probably redundant in all cases, because
' this Sub seems to freeze (and so effectively wait) until the timer task has finished!]...
While TimerRunning And CurrentCallTime = NextCallTime: DoEvents: Wend
End If
End Sub
我担心的是,一旦计划的任务开始,我将依靠上面的模块代码冻结作为“等待”功能的一部分。这是一种可靠的方法吗(OnTime过程是否总是中断并且优先于观察中可能出现的过程)?如果不使用API,是否会有更好的方法?
谢谢, 约翰。