“DoEvents”是什么意思?用vb6做的?

发布于 2024-10-08 22:13:37 字数 57 浏览 3 评论 0原文

vb6 中的“DoEvents”有什么作用? 为什么我收到错误消息“堆栈空间不足”?这是什么意思 ?

What does "DoEvents" do in vb6 ?
Why do I get the error message "Out of stack space" ? What does it mean ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

撧情箌佬 2024-10-15 22:13:37

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

您收到堆栈空间不足错误的原因可能是因为 DoEvents() 允许再次调用您的代码的事件发生,代码再次调用 DoEvents() ,依此类推,直到堆栈空间(跟踪所有这些事件的返回地址)话费,已经用完。

一般来说,我不建议使用 DoEvents(),因为存在此类问题,而且它违反了 Windows 的整体事件驱动设计。

DoEvents() allows other Windows messages to be processed.

The reason you get an out of stack space error is probably because DoEvents() is allowing events to occur that call your code again, which again calls DoEvents(), and so on until the stack space, which tracks the return addresses for all these calls, has run out.

In general, I do not recommend using DoEvents() due to problems like these and the fact that it violates the overall event-driven design of Windows.

抹茶夏天i‖ 2024-10-15 22:13:37

查看 DoEvents 的一个稍微不同的方式是它刷新事件队列中的事件。如果您的子程序或函数触发了一个事件,则该事件处理程序将成为一个子程序,一旦您的子程序/函数完成,就会立即运行。 DoEvents 表示立即运行该事件处理程序子程序,而不是等到子程序结束。

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

例如,当您使用 ProgressBar 控件时。假设您正在迭代数千条记录,并且希望通过更新进度条向用户提供有关当前进度的反馈。您可以每一百条记录中断循环并更改进度条控件上的值。但是(除非您对此采取措施),直到进度条的更改事件处理程序运行之后,您才会在屏幕上看到更改,并且该处理程序在您的子程序执行完毕之前不会运行。它只会被放入事件队列中。强制更改事件立即运行并挂起子进程的方法是调用 DoEvents。这将从队列中刷新所有现有事件(在本例中是进度条的更改事件),并将更新屏幕上的进度条控件。

现在,“堆栈空间不足”基本上意味着您陷入了函数调用的无限循环中。造成这种情况的最基本方法是:

Public sub MySub()
    MySub
End Sub

然后从某个地方调用 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

这种情况假设名为 TextBoxArray 的 TextBox 控件数组有两个成员。现在,如果用户从第一个(索引 0)开始并移动到第二个(索引 1),则将触发索引 0 的 LostFocus 事件。然而,VB 也会在内部将焦点设置到索引 1 框。然后代码会将焦点设置回索引 0,触发索引 1 的 LostFocus 事件!你陷入了循环。他们在 VB5 或 6 中通过等待 LostFocus 事件执行完成来设置焦点来解决这个问题。

A slightly different way of looking at DoEvents is that it flushes the events in the event queue. If your sub or function triggers an event, that event handler becomes a sub that is in line to run as soon as your sub/function is finished. DoEvents says to run that event handler sub now, instead of waiting till the end of your sub.

While I agree in spirit with Jonathon about not using DoEvents, I would temper his statement by saying I only recommend using it if you know exactly why, and know all of the repercussions of changing the order of the event queue this way. Most often, DoEvents is indicated when you want to update your screen in some way from within the context of a subroutine, before the subroutine is finished executing.

An example of this is when you are using the ProgressBar control. Suppose you are iterating through several thousand records, and want to provide feedback to the user as to how far along you are by updating a progress bar. You might interrupt your loop every hundred records and change the value on the progressbar control. However (unless you do something about it) you won't see the change on the screen until after the progressbar's change event handler runs, and that handler won't run until your sub is done executing. It will just get put in the event queue. The way to force the change event to run immediately, suspending your sub, is to call DoEvents. This will flush all existing events from the queue--in this case your progressbar's change event--and will update the progressbar control on the screen.

Now, "out of stack space" basically means that you've been caught in an endless loop of function calls. The most basic way to cause that is this:

Public sub MySub()
    MySub
End Sub

And then call MySub from somewhere. You'll get an out of stack space error. If you look at the Call Stack, you'll see a very long line of calls to MySub.

A well-known real-world example of this would happen in older versions of VB:

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

This situation assumes two members of a TextBox control array called TextBoxArray. Now, if the user starts with the first one (index 0) and moves to the second one (index 1) then index 0's LostFocus event will fire. However, VB would also internally set the focus to the index 1 box. Then the code would set the focus back to index 0, firing index 1's LostFocus event! You're caught in a loop. They fixed that in VB5 or 6 by waiting to set the focus until the LostFocus event was done executing.

離人涙 2024-10-15 22:13:37

我想澄清Johnathon的答案,因为它泵送VB消息循环并允许VB运行时处理Windows消息,这与睡眠相反,睡眠允许Windows处理其事件(在多核CPU和真正的多任务操作系统的世界中没有必要)但是当 VB6 编写时,Windows 9x 是占主导地位的操作系统,并且其中仅包含 DoEvents 的硬循环会将 CPU 使用率飙升至 100%)。因此,看到这样的事情

While fDoneFile = False
    DoEvents
    Sleep 55
Wend

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

I would clarify Johnathon's answer in that it pumps that VB message loop and allows the VB Runtime to process windows messages, which is the opposite of Sleep which allows for Windows to process its events (not necessary in the world of Multicore CPUs and true multitasking OS's but when VB6 was written Windows 9x was the dominant OS and a hard loop that only had DoEvents in it would spike the CPU usage to 100%). So seeing things like

While fDoneFile = False
    DoEvents
    Sleep 55
Wend

was a common pattern throughout the VB6 world.

无悔心 2024-10-15 22:13:37

如其他地方所述,DoEvents 允许触发应用程序中的其他事件。下面的示例说明了如何使用 DoEvents 而不会出现“堆栈空间不足”问题。这可以确保您不会通过使用布尔值来指示代码正在运行来多次运行代码。

Sub Example()
    'Create static variable to indicate the sub is running.
    Static isRunning As Boolean
    'Exit the sub if isRunning
    If isRunning Then Exit Sub
    'Indicate sub is running
    isRunning = True
    'Sub does stuff
    DoEvents
    'Ends up calling sub again
    Example 'Added just to prove via testing.
    'Indicate sub is no longer runningrunning
    isRunning = False
End Sub

As stated else where, DoEvents allows other events in your application to fire. Here's an example of how you can use DoEvents without the "Out of stack space" issue. This makes sure you don't run through the code multiple times by using a Boolean to indicate the code is running.

Sub Example()
    'Create static variable to indicate the sub is running.
    Static isRunning As Boolean
    'Exit the sub if isRunning
    If isRunning Then Exit Sub
    'Indicate sub is running
    isRunning = True
    'Sub does stuff
    DoEvents
    'Ends up calling sub again
    Example 'Added just to prove via testing.
    'Indicate sub is no longer runningrunning
    isRunning = False
End Sub
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文