Как избавиться от рекурсии Change в TextBox

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Sun07
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 355
Зарегистрирован: 17.02.2006 (Пт) 21:27

Как избавиться от рекурсии Change в TextBox

Сообщение Sun07 » 06.12.2006 (Ср) 4:18

При наступлении Change в TextBox надо присвоить новую строку , но при этом возникает опять вызов Change. Если установить флаг для обхода второго вызова Change и поставить первой строкой выход из процедуры по флагу, то этот флаг почему-то не сбрасывается в ноль, как поступить в таком случае? И вообще, нормально ли приводить в программе к вызову второго Change, когда первый ещё не закончен?

Код: Выделить всё
Private fNoChange as Byte

Private Sub TextBox1_Change()
     If fNoChange = 1 Then fNoChange = 0: Exit Sub
     fNoChange = 1 :TextBox1.Text=NewStr
'здесь ещё есть код
End Sub

Matew
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 894
Зарегистрирован: 28.06.2004 (Пн) 17:44
Откуда: Дальний Восток, г. Ха

Сообщение Matew » 06.12.2006 (Ср) 5:44

Вот так будет чуть лучше.
Код: Выделить всё
Private Sub TextBox1_Change()
    Static fNoChange As Boolean
     If fNoChange = True Then fNoChange = False: Exit Sub
     fNoChange = True: TextBox1.Text = NewStr
'здесь ещё есть код
End Sub
Алкоголь и сканеры-ваши враги! Не верите-смотрите аватару :-)

Sun07
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 355
Зарегистрирован: 17.02.2006 (Пт) 21:27

Сообщение Sun07 » 06.12.2006 (Ср) 8:01

и чем же стало лучше?

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Re: Как избавиться от рекурсии Change в TextBox

Сообщение Viper » 06.12.2006 (Ср) 8:04

Что-то вроде этого должно быть

Код: Выделить всё
Private fNoChange as Byte

Private Sub TextBox1_Change()
     If fNoChange = 1 Then  Exit Sub
     fNoChange = 1 :TextBox1.Text=NewStr
     'здесь ещё есть код
     fNoChange = 0
End Sub
Весь мир матрица, а мы в нем потоки байтов!

Sun07
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 355
Зарегистрирован: 17.02.2006 (Пт) 21:27

Сообщение Sun07 » 06.12.2006 (Ср) 8:09

!Viper!, ты молодец, я так и сделал. Но открытым остаётся вопрос о повторном вызове Change, когда первый Change ещё не завершился. Неужели это так и делается? И почему не работает мой первый вариант?
Последний раз редактировалось Sun07 06.12.2006 (Ср) 8:14, всего редактировалось 1 раз.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 06.12.2006 (Ср) 8:13

Код: Выделить всё
Private fBusyChange As Boolean
...
Private Sub Text1_Change()
If fBusyChange Then Exit Sub
fBusyChange = True
Text1.Text = NewStr
fBusyChange = False
End Sub
Lasciate ogni speranza, voi ch'entrate.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 06.12.2006 (Ср) 8:15

Явление под названием "повторный вызов Change" является вполне нормальным и естественным, ибо меняя в событии Change содержимое вызвавщего еге (событие) текстбокса, ты вызываешь повторный Change и так далее... Избавиться от этого нельзя, нужно правильно использовать флаги, что и показано в вышеприведенном коде
Весь мир матрица, а мы в нем потоки байтов!

Sun07
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 355
Зарегистрирован: 17.02.2006 (Пт) 21:27

Сообщение Sun07 » 06.12.2006 (Ср) 8:36

!Viper!, вот смотри, допустим, после вызова TextBox1.Text=NewStr идёт присвоение значение неким переменным, например, A=A+1 (переменная А описана как общая для проекта). А потом сразу идёт проверка этого значения if A=3 ... А после проверки условия ещё куча команд, после которых А=A*2. И представь, что у нашей не простой программы обход рекурсивного вызова происходит после двух рекурсивных вызовов. Какое значение будет иметь переменная А в момент проверки на первом рекурсивном вызове? И где гарантия, что второй рекурсивный вызов завершится позже первого, а вдруг ранее? :) Может, я привёл довольно корявый пример, да простят меня господа профессионалы, но вы же поняли, что я имею ввиду?

!Viper! , а ты можешь объяснить мне, почему в моём первичном примере fNoChange не обнуляется?

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 06.12.2006 (Ср) 9:07

Sun07 писал(а):!Viper! , а ты можешь объяснить мне, почему в моём первичном примере fNoChange не обнуляется?


А ты отладчиком его, отладчиком.
И все станет ясно...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Sun07
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 355
Зарегистрирован: 17.02.2006 (Пт) 21:27

Сообщение Sun07 » 06.12.2006 (Ср) 9:37

Andrey Fedorov, ничего подобного, отладчик не покажет рекурсивный вызов!

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 06.12.2006 (Ср) 9:39

Sun07 писал(а):Andrey Fedorov, ничего подобного, отладчик не покажет рекурсивный вызов!


Все прекрачным образом проходится.
Скорей всего им просто пользоваться не умеешь.
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Sun07
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 355
Зарегистрирован: 17.02.2006 (Пт) 21:27

Сообщение Sun07 » 06.12.2006 (Ср) 9:53

всё прекрасным образом НЕ проходится :). Ставлю брэкпоинт на If fNoChange=1 Then ... .Может, вы имеете ввиду отладчик не VB :shock: :D

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 06.12.2006 (Ср) 9:56

Sun07 писал(а):Может, вы имеете ввиду отладчик не VB :shock: :D


Вообще-то VB. Но дистанционно его работу все одно показать не смогу.
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Matew
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 894
Зарегистрирован: 28.06.2004 (Пн) 17:44
Откуда: Дальний Восток, г. Ха

Сообщение Matew » 06.12.2006 (Ср) 10:24

Народ, а зачем нужна лишняя глобальная переменная? Чем Static не угодил?
П.С. Может у меня руки кривые, но у меня все примеры работают :?
Алкоголь и сканеры-ваши враги! Не верите-смотрите аватару :-)

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 06.12.2006 (Ср) 10:27

Во-первых, статик медленнее.
Во-вторых, его нельзя инициализировать/установить снаружи. А флаги обычно устанавливаются из других процедур.
И в-третьих, а чем плох Private? Хотя, конечно, и Static можно использовать.
Lasciate ogni speranza, voi ch'entrate.

Matew
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 894
Зарегистрирован: 28.06.2004 (Пн) 17:44
Откуда: Дальний Восток, г. Ха

Сообщение Matew » 06.12.2006 (Ср) 10:33

alibek,
1. Не знал. :(
2. Здесь флаг точно местный.
3. Представь ситуцию, когда текстбоксов много. Тогда много лишних переменных висит в модуле.
4.(Против статика) У меня был случай когда статик переменные с одинаковыми именами перехлестывались (взаимоприсваивлись) из разных процедур, но это было до СП 6, может это поправили.
Алкоголь и сканеры-ваши враги! Не верите-смотрите аватару :-)

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 06.12.2006 (Ср) 10:44

alibek писал(а):Во-первых, статик медленнее.


И это сильно лимитирует в данной ситуации :lol:

alibek писал(а):Во-вторых, его нельзя инициализировать/установить снаружи. А флаги обычно устанавливаются из других процедур.


Зависит от ситуации. Я иногда Tag контрола для этого использую...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 06.12.2006 (Ср) 10:50

alibek писал(а):Во-первых, статик медленнее.

С какой стати?
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 06.12.2006 (Ср) 10:56

Ну правда медленнее, что тут сделаешь...
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 06.12.2006 (Ср) 11:15

А очень просто сделаю -- возьму да проверю.
Код: Выделить всё
Option Explicit

Private v2 As Long

Sub s1()
Static v1 As Long
Dim i As Double
    For i = 1 To 1000000000#
        v1 = v1 + 1
    Next
End Sub

Sub s2()
Dim i As Double
    For i = 1 To 1000000000#
        v2 = v2 + 1
    Next
End Sub

Sub Main()
Dim Start As Double
    Start = Timer
    s1
    MsgBox Timer - Start
    Start = Timer
    s2
    MsgBox Timer - Start
End Sub


Скомпилированное, у меня даёт 8.4 сек в обоих случаях. Машинный код различается на одно косвенное обращение, которое даже по сравнению с прибавлением единицы к даблу выполняется моментально.
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 06.12.2006 (Ср) 11:31

Блин, токно помню, что давно делал тесты, и было процентов на 30 медленнее. Теперь не получается :?
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 15

    TopList