Что делает DoEvents в vb6? - PullRequest
       8

Что делает DoEvents в vb6?

21 голосов
/ 24 декабря 2010

Что делает DoEvents в vb6? Почему я получаю сообщение об ошибке «Недостаточно места в стеке»? Что это значит?

Ответы [ 4 ]

18 голосов
/ 24 декабря 2010

DoEvents () позволяет обрабатывать другие сообщения Windows.

Причина, по которой вы получаете ошибку нехватки места в стеке, возможно, в том, что DoEvents () допускает события, которые снова вызывают ваш код, который снова вызывает DoEvents (), и так далее, пока пространство стека не отследит адреса возврата на все эти звонки кончились.

В общем, я не рекомендую использовать DoEvents () из-за подобных проблем и того факта, что он нарушает общий дизайн Windows, управляемый событиями.

6 голосов
/ 31 мая 2013

Немного другой взгляд на DoEvents состоит в том, что он сбрасывает события в очереди событий. Если ваша подпрограмма или функция запускает событие, этот обработчик событий становится подпрограммой, которая должна быть запущена, как только ваша подпрограмма / функция будет завершена. DoEvents говорит, что теперь нужно запускать эту подпрограмму обработчика событий, а не ждать конца своей подпрограммы.

Хотя я согласен с Джонатоном в духе отказа от использования DoEvents, я бы умерил его высказывание, сказав, что рекомендую использовать его, только если вы точно знаете, почему, и знаете все последствия изменения порядка очереди событий таким образом. Чаще всего DoEvents указывается, когда вы хотите каким-либо образом обновить экран из контекста подпрограммы, прежде чем подпрограмма будет завершена.

Примером этого является использование элемента управления ProgressBar. Предположим, вы перебираете несколько тысяч записей и хотите предоставить пользователю обратную связь о том, как далеко вы продвинулись, обновив индикатор выполнения. Вы можете прерывать цикл через каждые сто записей и изменять значение в элементе управления 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

В этой ситуации предполагается наличие двух членов массива элемента управления TextBox с именем TextBoxArray. Теперь, если пользователь начинает с первого (индекс 0) и переходит ко второму (индекс 1), событие LostFocus индекса 0 сработает. Однако VB также внутренне установил бы фокус на поле индекса 1. Затем код установит фокус обратно на индекс 0, запустив событие индекса 1 LostFocus! Вы попали в петлю. Они исправили это в VB5 или 6, ожидая установки фокуса, пока не завершилось выполнение события LostFocus.

5 голосов
/ 27 декабря 2010

Я бы пояснил ответ Джонатона в том, что он прокачивает этот цикл сообщений VB и позволяет среде выполнения VB обрабатывать сообщения Windows, что противоположно Sleep, который позволяет Windows обрабатывать свои события (не обязательно в мире многоядерных процессоровнастоящие многозадачные ОС, но когда был написан VB6, Windows 9x была доминирующей ОС, и жесткий цикл, в котором были только DoEvents, увеличил бы загрузку процессора до 100%).Так что видение таких вещей, как

While fDoneFile = False
    DoEvents
    Sleep 55
Wend

, было обычным явлением во всем мире VB6.

4 голосов
/ 10 октября 2012

Как указано еще где, DoEvents позволяет запускать другие события в вашем приложении.Вот пример того, как вы можете использовать DoEvents без проблемы «Out of stack space».Это гарантирует, что вы не запускаете код несколько раз, используя логическое значение, чтобы указать, что код работает.

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
...