А готовых выносок как в мелкософт офисе нет нигде?
Ни куда они не ушли. Клава, мышь, некоторые другие устройства обслуживаются прерываниями. Еще стоит заглянуть в IDT и посмотреть - там куча заюзаных векторов. Многие из них постоянно используются как программистами, так и самой системой:Прерывания ушли в небытие. Нет прерываний. Единственное прерывание, которое работает как прерывание, но до которого тебе далеко не добраться -- прерывание, осуществляющее переключение между задачами процессора
Хакер писал(а):Что в данном случае принимать за таймер?
Хакер писал(а):Ерунда. Если один таймер (т.е. внутри Timer1_Timer'а работает бесконечный цикл), то ничего кроме этого цикла в рамках потока вообще не работает.
По сути, у тебя происходит примерно следующее:
На самом же деле, тыбе бы сейчас "помог" "неждущий таймер", о котором так мечтал arthur2. Однако помог бы он тебе только визуально: всё бы выглядело хорошо, а на деле появилась бы бесконечно растущая рекурсия.
А чтобы не появлялась "бесконечно растущая рекурсия", достаточно в процедуре тика объявить статический флаг, устанавливать его на входе и снимать на выходе. А если на входе флаг уже стоит (предыдущий тик ещё работает), выходить из процедуры сразу.
в теле события таймера производятся действия. Если во время них начать тягать скроллбар - таймер больше не работает, пока мышь не отпущу. Но если схватиться за скроллбар в промежутке между срабатываниями таймера - он продолжает давать свои евенты.
Но можно сделать КРБ "наизнанку" - если второй тик сработал, а первый ещё не закончился, прерывать не второй, а первый, подвешенный тик.
Второй тик смотрит, докуда там довычислялся первый, затем устанавливает флаг, что первому нужно завершиться, а сам продолжает вычисление.
Первый завершится сразу же, как будет отпущен скрол. Скролом ведь задержен один-единственный тик - тот, во время которого скрол тягали. После того как скрол отпустят, тик захочит продолжить вычисления, но увидит, что флаг установлен - уже работает следующий тик - и спокойно завершится. Просто нужно два флага - один статичный в процедуре о том, завершилась процедура или нет, второй на уровне модуля - о том, что нужно прервать цикл.И первый не завершится, прока не завершится второй
Первый завершится сразу же, как будет отпущен скрол. Скролом ведь задержен один-единственный тик — тот, во время которого скрол тягали. После того как скрол отпустят, тик захочит продолжить вычисления, но увидит, что флаг установлен - уже работает следующий тик — и спокойно завершится
Sub A
Call B
End Sub
Sub B
' А вот тут ты хочешь "завершить" работающую в этот момент процедуру A.
End Sub
Как-то так, что флаг, установленный в выполняющемся обработчике одного тика, может быть проверен из другого тоже выполняющегося в данный момент обработчика?
Dim cntSomething As Long, flExit As Boolean
Private Sub iTimer_Tick(ByVal idTimer As Long, tmNow As Long)
Static flKRB As Boolean
If flKRB Then' если ещё обрабатывается предыдущий тик
flKRB = False
flExit = True
Exit Sub
End If
flKRB = True
Do While cntSomething < 1000000000
DoEvents
If flExit Then flExit = False: Exit Sub
Call DoSomething
cntSomething = cntSomething + 1
Loop
flKRB = False
End Sub
Private Sub DoSomething()
Dim s As String
s = Space(100000) & Space(100000)
End Sub
Я не понял, почему цикл не прервётся по флагу, установленному из другой процедуры.
Рекурсии-то не возникнет.
Private Sub ITimer_Tick(ByVal idTimer As Long, tmNow As Long)
flExit = Not flExit
If flExit Then Exit Sub
Do 'выход из цикла вообще только по флагу. И тем не менее, он всё время нормально срабатывает
DoEvents
If flExit Then
Debug.Print "flExit " & cntSomething
flExit = False: Exit Sub
End If
Call DoSomething
cntSomething = cntSomething + 1' условно - оставляем информацию для следующего тика, до куда довычислялся предыдущий
If cntSomething > 100000000 Then cntSomething = 1
Loop
End Sub
Private Sub DoSomething()
Dim s As String
s = Space(1000000) & Space(1000000)
End Sub
А я что сделал? Ну поставь вместо дебаг.принт смену цвета шейпа. Эта смена не замирает, сколько бы ни тискали скрол.Ты возьми первый пример автора, и переделай его так
Ну поставь вместо дебаг.принт смену цвета шейпа.
Ты возьми первый пример автора, и переделай его так...
Да мне что, делать больше нечего, кроме как переделывать какие-то примеры, чтобы доказать заблуждающемуся, что код всё-так выполняется линейно, не в хаотичном порядке?
Без понятия. Но ведь не возникает!Ты сможешь сказать точно: куда делась рекурсия? Почему она не возникает? Я могу точно сказать, почему она должна возникать. Ты можешь с такой же твёрдостью сказать, почему у тебя рекурсия не возникает?
Без понятия. Но ведь не возникает!
А почему не возникает рекурсия у нескольких подряд вообще голых тиков, если каждый следующий вызывается из предыдущего? Я не знаю, почем, но ведь не возникает же?
Я давно использую таймеры, чтобы прерывать циклы. Выставить флаг из обычной процедуры, чтобы цикл его увидел - действительно не получится. А вот из таймера - запросто.
и почему ты утверждаешь, что каждый следующий вызывается из предыдущего
Фактически, если сделать принять это как множество бинарных отношений "кто кого запустил" и сделать транзитивное замыкание, то мы получим, что фактически обработчик первого тика вызывает обработчик второго тика.
Ну чушь это. Не надо обожествлять таймеры.
Я смогу её завершить - если в ней стоит проверка флага, а флаг установить таймером.
- Код: Выделить всё
Sub A
Call B
End Sub
Sub B
' А вот тут ты хочешь "завершить" работающую в этот момент процедуру A.
End Sub
Сейчас этот форум просматривают: AhrefsBot, Google-бот, Yandex-бот и гости: 61