强制事件循环,比如
1.
Do While True
   Debug.print Time
Loop
这个语句执行后无法退出,一直在执行,也不能执行其它任何操作2.
Do While True
   Debug.print Time
   DoEvents
Loop
这个语句中,虽然循环永远无法退出,但因为加上了DoEvents语句,强制事件循环
所以在Loop语句之外的事件仍能触发!

解决方案 »

  1.   

    DoEvents 将控制切换到操作环境内核。只要此环境中的所有应用程序都有机会响应待处理事件,应用程序就又恢复控制。这不会使应用程序放弃焦点,但会使后台事件能够得到处理。'举例如下:添加List1和Command1
    '加入DoEvents后,在添加列表项时,仍可以响应你的操作,如拖动窗口
    '不加入DoEvents,你必须等到添加列表项完毕时才可以如拖动窗口
    Private Sub Command1_Click()
      List1.Clear
      For i = 0 To 10000
        List1.AddItem CStr(i) & "-" & CStr(i + 1) & "-" & CStr(i + 2)
        Me.Caption = CStr(i + 1)
        'DoEvents
      Next
    End Sub以下节选自MSDN
    使用 DoEvents
    尽管 Timer 事件是后台处理的最好工具,对耗时极多的任务,情况更是如此,但是,DoEvents 函数还是提供了一种取消任务的简便方法。例如,下列代码将显示一个 "Process" 按钮,单击这个按钮时,它将变成 "Cancel" 按钮。再次单击按钮又将中断正在执行的任务。'此按钮最初的标题是 "Process"。
    Private Sub Command1_Click()
       '过程的所有实例都
       '共享静态变量。
       Static blnProcessing As Boolean
       Dim lngCt As Long
       Dim intYieldCt As Integer
       Dim dblDummy As Double
       '按下按钮时,检测是否
       '已经在处理。
       If blnProcessing Then
          '如果正在处理,则取消处理。
          blnProcessing = False
       Else
          Command1.Caption = "Cancel"
          blnProcessing = True
          lngCt = 0
          '执行一百万次浮点
          '乘法计算。每一千次后,
          '检测是否要取消。
          Do While blnProcessing And (lngCt < 1000000)
             For intYieldCt = 1 To 1000
                lngCt = lngCt + 1
                dblDummy = lngCt * 3.14159
             Next intYieldCt
             'DoEvents 语句允许其它事件
             '发生,包括第二次
             '按此按钮。
             DoEvents
          Loop
          blnProcessing = False
          Command1.Caption = "Process"
          MsgBox lngCt & " multiplications were performed"
       End If
    End SubDoEvents 将控制切换到操作环境内核。只要此环境中的所有应用程序都有机会响应待处理事件,应用程序就又恢复控制。这不会使应用程序放弃焦点,但会使后台事件能够得到处理。这种妥协的结果可能并不总是达到预期目标。例如,下述 Click 事件代码在单击按钮后要一直等候十秒钟,而后才显示一条信息。如果在按钮正在等待期间单击它,则将以相反顺序完成单击操作。Private Sub Command2_Click()
       Static intClick As Integer
       Dim intClickNumber As Integer
       Dim dblEndTime As Double
          '每次单击按钮时
          '赋予唯一数值。
       intClick = intClick + 1
       intClickNumber = intClick
          '等待十秒。
       dblEndTime = Timer + 10#
       Do While dblEndTime > Timer
          '不做任何事情,仅仅允许
          '其它应用程序处理
          '它们的事件。
          DoEvents
       Loop
       MsgBox "Click " & intClickNumber & " is finished"
    End Sub对于通过 DoEvents 放弃控制的事件过程,有时可能希望防止在 DoEvents 返回之前重新调用这一过程。否则将无穷无尽地调用该过程,直到系统资源消耗殆尽。可暂时禁止控件,或象上例一样,使用一个静态的“标志”变量防止此事发生。在使用全局数据时避免 DoEvents
    当一个函数已通过 DoEvents 放弃控制时,可相当安全地再次调用函数。例如,下一过程将检测质数并用 DoEvents 语句周期地启动其它应用程序处理事件:Function PrimeStatus (TestVal As Long) As Integer
       Dim Lim As Integer
       PrimeStatus = True
       Lim = Sqr(TestVal)
       For I = 2 To Lim
          If TestVal Mod I = 0 Then
             PrimeStatus = False
             Exit For
          End If
          If I Mod 200 = 0 Then DoEvents
       Next I
    End Function该代码中每重复 200 次就调用一次 DoEvents 语句。这样一来,当该环境的其余部分对事件作出响应时,只要有必要,PrimeStatus 过程就可继续计算。考虑在调用 DoEvents 期间发生的事情。在其它窗体和应用程序处理事件时将暂停执行应用程序代码。这些事件之一有可能是一个按钮单击操作,它将再次启动 PrimeStatus 过程。这将导致重新进入 PrimeStatus 过程的,但是,因为在函数每次出现时,堆栈都为其参数和局部变量分配了空间,所以重入不会引发冲突。当然,如果过多调用 PrimeStatus,则可能出现“溢出堆栈空间”错误。如果 PrimeStatus 使用或改变模块级变量或全局数据,情况就会完全不同。此时,在 DoEvents 能够返回之前执行 PrimeStatus 的另一个实例,这将导致模块数据或全局数据的值完全不同于它们在调用 DoEvents 之前的值。于是,PrimeStatus 的结果将会难以预料。详细信息 请参阅“语言参考”的“DoEvents 函数”和“Refresh 方法”。