"DoEvents"在vb6中做了什么?

far*_*oft 21 vb6 doevents

"DoEvents"在vb6中做了什么?为什么我收到错误消息"堆栈空间不足"?这是什么意思 ?

Jon*_*ood 18

DoEvents()允许处理其他Windows消息.

出现堆栈空间错误的原因可能是因为DoEvents()允许再次调用代码的事件,再次调用DoEvents(),依此类推,直到堆栈空间跟踪所有这些的返回地址电话,已经用完了.

一般情况下,我不建议使用DoEvents(),因为这些问题以及它违反了Windows的整体事件驱动设计.

  • +1尽管现在我们已经看到了异步编程的最新思想,[异步CTP](http://msdn.microsoft.com/en-us/vstudio/gg316360),也许DoEvents看起来很现代? (4认同)

Bob*_*des 6

查看DoEvents的一种略微不同的方式是刷新事件队列中的事件.如果您的子或函数触发了一个事件,那么该事件处理程序将成为一个子元素,该子元素在您的子/函数完成后立即运行.DoEvents现在说要运行该事件处理程序子,而不是等到子结束.

虽然我在精神上同意Jonathon关于不使用DoEvents的意见,但我会说他只是建议你使用它,如果你确切知道原因,并且知道以这种方式更改事件队列顺序的所有后果.大多数情况下,当您想要在子例程执行完成之前以某种方式从子例程的上下文中更新屏幕时,会指示DoEvents.

例如,当您使用ProgressBar控件时.假设您正在迭代数千条记录,并希望通过更新进度条向用户提供有关您的距离的反馈.您可能会每隔一百条记录中断循环并更改进度条控件上的值.但是(除非你对它做了一些事情)直到进度条的更改事件处理程序运行之后才会在屏幕上看到更改,并且在子程序执行完之后该处理程序将不会运行.它将被放入事件队列中.强制change事件立即运行,暂停sub的方法是调用DoEvents.这将刷新队列中的所有现有事件 - 在这种情况下是您的进度条的更改事件 - 并将更新屏幕上的进度条控件.

现在,"超出堆栈空间"基本上意味着你已经陷入了无限循环的函数调用.导致这种情况的最基本方法是:

Public sub MySub()
    MySub
End Sub
Run Code Online (Sandbox Code Playgroud)

然后从某个地方调用MySub.你会得到一个堆栈空间错误.如果你看一下调用堆栈,你会看到很长的MySub调用.

在旧版本的VB中会出现一个众所周知的现实示例:

Public Sub TextBoxArray_LostFocus(index as Integer)
    If TextBoxArray(index) = "" Then
        TextBoxArray(index).SetFocus
        MsgBox "Please enter a value"
    End If
End Sub
Run Code Online (Sandbox Code Playgroud)

这种情况假设一个名为TextBoxArray的TextBox控件数组的两个成员.现在,如果用户以第一个(索引0)开始并移动到第二个(索引1),则将触发索引0的LostFocus事件.但是,VB也会在内部将焦点设置为索引1框.然后代码将焦点设置回索引0,触发索引1的LostFocus事件!你陷入了困境.他们通过等待设置焦点直到LostFocus事件执行完毕,在VB5或6中修复了它.


Kri*_*son 5

我会澄清Johnathon的答案,因为它泵出VB消息循环并允许VB运行时处理Windows消息,这与Sleep相反,允许Windows处理其事件(在多核CPU和真正的多任务操作系统的世界中不是必需的)但是当编写VB6时,Windows 9x是主流的操作系统,而且只有DoEvents的硬循环会将CPU使用率提高到100%.所以看到类似的东西

While fDoneFile = False
    DoEvents
    Sleep 55
Wend
Run Code Online (Sandbox Code Playgroud)

是整个VB6世界的常见模式.