Таймер своими руками (обёртка к SetTimer)

Здесь можно найти готовые «кирпичики» — части кода, пригодные для построения более крупных проектов, а также решения различных типовых и не очень задач на VB.

Модератор: Brickgroup

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Таймер своими руками (обёртка к SetTimer)

Сообщение arthur2 » 14.05.2008 (Ср) 16:39

Давно время от времени пользуюсь Апи-таймером - у него есть одно огромное преимущество перед стандартным бейсиковским.

Но недавно понадобилось мне сделать сразу несколько таймеров в разных формах и классах. Чтобы не изобретать велосипеда, стал искать удобную обёртку... Единственное, что нашёл - "классический" класс XTimer http://bbs.vbstreets.ru/download.php?id=6283

И этот класс мне совершенно не понравился. Во-первых, его нужно объявлять Withevents, в связи с чем ни каких тебе массивов. Десять таймеров - замучаешься объявлять. А во-вторых, и это важнее - в этой реализации таймер каким-то образом оказался лишён своего ГЛАВНОГО достоинства. (дописано позднее: как выяснилось из обсуждения, указанное достоинстов пропадает только в режиме отладки, а после компиляции возвращается, но это значит, что такая реализация неудобна в отладке)

В общем, написал свою обёртку. Вместо Withevents использовал Implements (огромное спасибо Хакеру, что понятно объяснил, как это действует - теперь вот пользуюсь где ни попадя).

Можно создать любое количество таймеров в любом классе, форме, контроле (в пределах разумного, конечно). Бейсик, вроде, не падает. Отладка нормально работает (а таймеры при этом не останавливаются!) :)

Кстати, где-то читал про ограничение на количество таймеров в одной программе... То-ли 8, то ли 15. Ни какого ограничения не заметил - 500 таймеров одновременно тикают как часы :lol:

Ах, да, что за преимущество-то? Главное? См. тестовый проект в примере. Особенно третий тест.
Вложения
myTimer.zip
Таймер своими руками (обёртка к SetTimer)
(13.6 Кб) Скачиваний: 209
Последний раз редактировалось arthur2 18.05.2008 (Вс) 20:05, всего редактировалось 2 раз(а).
Артур
 
   

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 14.05.2008 (Ср) 19:12

Там идёт вызов напрямки в форму/класс, да? Поздравляю с новообретённой утечкой памяти
Если какой-то класс создаст таймер, установив обработчиком себя, а уничтожение таймера будет происходит в Class_Terminate, то класс НИКОГДА не будет уничтожен, поскольку на него есть ссылки в модуле, что приводит к утечкам памяти. Это особенности COM, и от них никуда не денешся, хоть и есть обходные пути.
Ну, ещё ReDim Preserve очень неэффективная штука, когда идёт добавление по одному элементу, хотя в данном случае это не так важно.
Изображение

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 14.05.2008 (Ср) 20:19

keks-n

Любой класс при своём уничтожении должен сообщить модулю, чтобы его таймеры тоже уничтожились. Так вот - в той же процедуре уничтожается и ссылка на класс, так что проблеммы не вижу - когда класс умирает, ссылки на него в модуле уже нет. По крайней мере, все создаваемые классы в тестовом проекте успешно справлялись со своим уничтожением (см. четвёртый тест).

Про Redim. Чтобы лишний редим не происходил, нужно просто сначала создать таймер с самым большим индексом, только и всего (в коде, кстати, на это вниманее обращено - там где запускаются 500 таймеров). Но реально очень сомнительно, что понадобится столько много таймеров, ещё более сомнительно, что слишком много классов одновременно будут создавать себе таймеры, так что
в данном случае это не так важно
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 14.05.2008 (Ср) 21:05

keks-n
Нашёл ту проблемму, про которую ты говоришь. Действительно, при попытке явно уничтожить класс Terminate не наступает. Впрочем, при завершении программы все классы нормально терменятся, так что проблемма не большая.

Но если по ходу программы планируется много классов, которым уготовано умирать вручную, то в таких классах просто нужно предусмотреть процедуру типа "отпустите меня перед смертью" и гасить таймеры оттуда, а не из Class_Terminate. После этого явное уничтожение класса нормально работает.
Артур
 
   

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 15.05.2008 (Чт) 9:05

Во-первых, его нужно объявлять Withevents, в связи с чем ни каких тебе массивов.
Ерунда какая. Несложно дописать класс-коллекцию и вместо генерации события научить XTimer дергать ее метод, который будет генерить событие самой коллекции с идентификатором соответствующего таймера (аттач).
А во-вторых, и это важнее - в этой реализации таймер каким-то образом оказался лишён своего ГЛАВНОГО достоинства.
КАКОГО? :shock:
Впрочем, при завершении программы все классы нормально терменятся, так что проблемма не большая.
Это таки проблема большая. Если использовать не Standart Exe, а ActiveX exe, то процесс останется висеть в памяти. Да и в стандартном я могу придумать кучу похожих ситуаций.
Вложения
XTimers.rar
(2.58 Кб) Скачиваний: 126
Лучший способ понять что-то самому — объяснить это другому.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 15.05.2008 (Чт) 13:02

Ну и зачем ты ещё раз повторил всё то же самое, на что я уже ответил?

1. Переделать - это уже другая песня. В том варианте, в котором он был, он мне не понравился. В новом варианте, кстати, тоже - главное не withevents, а п.2 А ещё - у меня таймеры генерят свои события практически напрямую клиенту, а у тебя через трёх посредников (коллекцию, класс с коллекцией и сам класс таймера).

2. Главное достоинство - сказал же, см. третий тест (если уж так в лом скачать и посмотреть, то вот - следующее событие таймера отсчитывается не от конца, а от начала предыдущего - запусти из события таймера msgbox - и стандартный таймер (как и Хтаймер) будет тупо ждать, пока ты закроешь окно, вместо того, чтобы тикать дальше)

3. "Это таки проблема большая" лялляля... Ещё раз отвечаю - обычно это не проблема, но если в конкретном случае это проблема, гашение таймеров (а с ним произойдёт и уничтожение ссылки на класс) нужно делать не в Class_Terminate, а вручную. Тогда класс нормально уничтожается. В любом случае, это проблемма не моего модуля, а того класса, вкоторый будет его использовать (можно ведь и таймеры забыть уничтожить - тогда вообще всё будет рушиться).

И о птичках - твой XTimers с коллекцией этой же самой проблеммой страдает (только она там как раз так запрятана, что снаружи не доберёшся). Брось на форму кнопку и ей уничтож XTimers. Поставь бреки на Class_Terminate - XTimers уничтожается, а вот итемы XTimer остаются висеть до завершения программы. Так что "Это таки проблема большая"
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16111
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 15.05.2008 (Чт) 15:14

2.
стандартный таймер (как и Хтаймер) будет тупо ждать, пока ты закроешь окно, вместо того, чтобы тикать дальше

А у тебя что будет, если в обработчике таймера поставить MsgBox и не закрывать его, и при этом пройдёт время интервала?
Страшно предположить.
а) Создаться новый поток, в которов создатся новый MsgBox?
б) События поставятся в очередь, а по закрытию MsgBox-а начнут сразу же обрабатываться? Чтобы всё к чертём зависло?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 15.05.2008 (Чт) 15:31

в) Собтия попадают в очередь и обрабатываются сразу же после этого, не ожидая закрытия msg(а собственно с чего бы им ожидать?)
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 15.05.2008 (Чт) 15:47

Хакер
А ты попробовал, прежде чем возразить? Ничего особенного не будет. Покажется сразу несколько боксов, и всё. Ничего не зависнет. См тест 1 и тест 2. Мало того, если в событии будет какое-то ну очень длинное действие, то следующее событие всё равно наступает, даже если предыдущее всё ещё обрабатывается. См. третий тест.

ANDLL
Вот именно!

Кстати, именно так ведёт себя Апи-таймер без всякой обёртки - а ХТаймер это свойство каким-то образом убивает. В связи с чем ХТаймер в топку.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16111
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 15.05.2008 (Чт) 16:01

arthur2
Ты относишься к той категории людей, для которой светофор - это не преимущество, контролирующее движение и позволяющее предотвращать аварии, а недостаток, на котором иногда нужно останавливаться, что иногда напрягает?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 15.05.2008 (Чт) 16:23

arthur2 писал(а):Ну и зачем ты ещё раз повторил всё то же самое, на что я уже ответил?
Так уж ты ответил, что с первого раза не понятно. :roll:

2) Качал, смотрел, структура файлов и код оформлены безобразно, сразу не понял, что надо было запускать, досконально разбираться времени не было.
И о птичках
Исправлено. Опять же без поползновений извне. Рекомендую тебе сделать аналогично: Dim iTmr() As ITimer > Dim iTmr() As Long.
Вложения
XTimers.rar
(2.63 Кб) Скачиваний: 124
Лучший способ понять что-то самому — объяснить это другому.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 15.05.2008 (Чт) 16:29

Хакер
Ты скачал и попробовал пример? Ты попробовал его уронить? О чём мы говорим. Естественно, мой пример не без недостатков. Но это никак не то, о чём ты говоришь.

Посмотри же наконец третий тест - мой таймер за 60 секунд делает ровно 60 тиков, при том что в его событии:

Код: Выделить всё
For i = 0 To 10000 ' имитируем выполнение сложной задачи
    s = Space(100000)
    s = vbNullString
    DoEvents
Next


Стандартный таймер при таком раскладе натикивае 60 раз минуты за две.

То, что точность и регулярность тиков так сильно зависит от выполняемой задачи - недостаток для таймера.

А ненодёжность моего таймера ты не доказал. Вполне допускаю, что она есть, но в чём она?
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 15.05.2008 (Чт) 16:32

Antonariy
Безобразно - ну что есть, то есть. Никто меня оформлению не учил, самоучки мы-с... :lol:

Сейчас посмотрю. Dim iTmr() As Long - это кажется интересно.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16111
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 15.05.2008 (Чт) 16:49

Безобразно - ну что есть, то есть. Никто меня оформлению не учил, самоучки мы-с...


Надо же? Меня тоже никто не учил. Но тем не менее, оформление на высоте.

Это всё отговорки, про "никто не учил". Элементарная лень.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 15.05.2008 (Чт) 17:16

Хакер
Опять снобствуешь в офтопе? Да, я менее талантлив в програмировании, чем ты. Возможно, я даже бездарь. Занимаюсь этим уже 10 лет - как был делитантом, так и остался. Да, ты гений (что талантлив - ничуть не сомниваюсь, и совершенно без иронии). А я, вероятно, лентяй. Но может всё же вернёмся к нашим баранам?

Antonariy
Про ITimer() as long: Здорово. Но мне до конца не понятно - чтобы присвоить такому объекту Nothing, его нужно доставать с помощью ObjFromPtr ?

Про ХТаймерс: интересно, а в чём там мудрёная защита, что он не генерит события, пока не закончилось предыдущее? Может эту волшебную защиту можно как-то снять? До этих пор он мне как не нравился, так и не нравится.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16111
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 15.05.2008 (Чт) 17:57

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

Но может всё же вернёмся к нашим баранам?

Возвращайся.

Про ITimer() as long: Здорово. Но мне до конца не понятно - чтобы присвоить такому объекту Nothing, его нужно доставать с помощью ObjFromPtr ?

Чтобы присвоить такой ссылке (а не объекту) Nothing, надо присвоить ей 0&, предварительно вызвав у объекта метод Release

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

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

Приведи мне пример, когда бы тебе (конкретно тебе, arthur2) понадобился такой таймер, который работает допускает рекурсивно зацикливаться?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 15.05.2008 (Чт) 18:28

Про ITimer() as long: Здорово. Но мне до конца не понятно - чтобы присвоить такому объекту Nothing, его нужно доставать с помощью ObjFromPtr ?
Тебе этот способ все-таки не подойдет. У тебя ITimer'ы хранятся только в массиве, а в XTimers - в коллекции + в массиве в модуле. Из-за того, что ссылки хранились в массиве, икстаймеры не убивались при убитии коллекции. Я заменил в массиве ссылку на указатель, единственная ссылка осталась в коллекции. У тебя же все происходит только в модуле - без убития снаружи не обойтись.
Лучший способ понять что-то самому — объяснить это другому.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 15.05.2008 (Чт) 18:57

ХакерПро отмазки - ну ладно, отмазки. Только что делать-то? Ты не видел ещё мой стиль десятилетней давности, когда я и печатать толком не умел. Тогда стиль не казался мне чем-то очень важным, а сейча - это уже мой новый стиль и я вряд ли смогу, да и захочу переучиваться. Я свой код понимаю, а глазами специалиста взглянуть на него всё равно не могу. Теперь уже - горбатого могила :lol: Но я програмистом не работаю, и в лени меня обвинять не надо - я может пашу по-больше твоего, в том числе и в бейсике, иногда пробивая-таки стену лбом (хотя дверь рядом, но пробегающие мимо Хакеры обычно считают, что для меня полезней будет додолбиться как-нибудь самому)

Чтобы присвоить такой ссылке (а не объекту) Nothing, надо присвоить ей 0&, предварительно вызвав у объекта метод Release


У меня было:
Код: Выделить всё
Dim ITmr() as ITimer
Затем Set ITimer(index) = itm


Мне предложили:
dim iTmr() as long
iTmr(index)=objptr(itm)


А затем, когда понадобится сам объект:
Код: Выделить всё
dim tmp as ITimer
CopyMemory Tmp, itmr(index), 4
call tmp.tick (трампампам)
CopyMemory Tmp, 0&, 4


Вот мне и интересно, когда в itm придёт Nothing, как нужно обрабатывать такую ситуацию? И вообще, кстати, безопасен ли такой метод? А то может всё же оставить как было?

Приведи мне пример, когда бы тебе (конкретно тебе, arthur2) понадобился такой таймер, который работает допускает рекурсивно зацикливаться?

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

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

[/quote]
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 15.05.2008 (Чт) 19:12

Antonariy

Да, обидно - а я уже было облизнулся :lol:
Но сам способ очень интересный! Я его запомню.

А кроме того, что исправил некорректное убиение, не желаешь выдрать из ХТаймера дуратскую подушку безопасности? А то п.2 так и остался в силе.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16111
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 15.05.2008 (Чт) 19:15

arthur2 писал(а):Но я програмистом не работаю, и в лени меня обвинять не надо - я может пашу по-больше твоего, в том числе и в бейсике, иногда пробивая-таки стену лбом (хотя дверь рядом, но пробегающие мимо Хакеры обычно считают, что для меня полезней будет додолбиться как-нибудь самому)

:?

arthur2 писал(а):
Чтобы присвоить такой ссылке (а не объекту) Nothing, надо присвоить ей 0&, предварительно вызвав у объекта метод Release


У меня было:
Код: Выделить всё
Dim ITmr() as ITimer
Затем Set ITimer(index) = itm


Мне предложили:
dim iTmr() as long
iTmr(index)=objptr(itm)


А затем, когда понадобится сам объект:
Код: Выделить всё
dim tmp as ITimer
CopyMemory Tmp, itmr(index), 4
call tmp.tick (трампампам)
CopyMemory Tmp, 0&, 4


Вот мне и интересно, когда в itm придёт Nothing, как нужно обрабатывать такую ситуацию? И вообще, кстати, безопасен ли такой метод? А то может всё же оставить как было?


1) Для начала надо определиться, для чего ты делаешь переход с автоматического COM, на ручной COM?
Что замена даст? По скорости ты не выиграешь. По размеру кода - не выиграешь. По гладкости - также.

2) Случай, когда itm будет ссылаться на Nothing, надо обрабатывать вручную перед первым использованием itm, и если оно вдруг ссылаетсян на Nothing -- генерировать самому ошибку Object variable or with block variable not set.


В тесте - только пример, демонстрирующий саму проблемму.

Проблему.
Мне не нужно, чтобы таймер рекурсивно зацикливался. Я только допускаю ситуацию (конкретную ситуацию), когда один из тиков (не каждый!) может обрабатываться довольно долго. И я не хотел бы, чтобы таймер в этот момент замер. И уж совсем бы не хотелось, чтобы всякий раз, когда я вызываю какое-нибудь модальное окно (не обязательно msgbox), все мои таймеры замирали. Если уж на то пошло, копать в сторону апи-таймера я и начал как раз тогда, когда столкнулся с задачей, в которой стандартный таймер начал выделывать кренделя.

Модальное окно на то и модальное, чтобы приложение замирало, пока оно открыто.

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

Эта защита никому, похоже, кроме тебя не мешает. Вспоминается пословица про плохого танцора и его туфли.

Почему ты постоянно считаешь, что если я что-то сказал, я обятельно должен привести 10 примеров, выложит сотни сток кода, чтобы дополнить этим сказанное?

Ну ладно. Представь в что у тебя в обработчике таймера произошла ошибка. Out of memory. А таймер всё ещё работает. И открывает мессаги, открывает, открывает. Пока ресурсы "оконное подсистемы" не закончатся.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 15.05.2008 (Чт) 23:29

Ну ладно. Представь в что у тебя в обработчике таймера произошла ошибка. Out of memory. А таймер всё ещё работает. И открывает мессаги, открывает, открывает. Пока ресурсы "оконное подсистемы" не закончатся.
Ты хоть сам понял, что сказал? :lol:
Во-первых, кому надо в каждом тике выводить модальное окно? Я лично не могу представить такой надобности. А один-два раза могу вполне.
Во-вторых, нормальные люди ошибки обрабатывают.
Ну и в-третьих, с exe не произойдет ровном счетом НИЧЕГО (ide будет неактивно, если нажать debug, и рухнет, если end). Я засунул во втором тесте If cntTic = 2 Then Err.Raise 999 в ITimer_Tick - просто не вывелся соответствующий MsgBox.
Проблему
Конечно, это самое важное в данном обсуждении. Достойно комментария, занесения в цитаты и коллекцию избранных топиков.
Модальное окно на то и модальное, чтобы приложение замирало, пока оно открыто.
Не "приложение замирало", а были бы недоступны юзеру ранее открытые формы. Если нужно - пусть работает.
Эта защита никому, похоже, кроме тебя не мешает.
Случается, что мешает. Не помню, что делал, но тоже наткнулся на то, что обычный таймер замирал при выводе модальной формы. Пришлось передать ссылку на вызвавшую форму в модальную и дергать ее процедуру таймером из модальной формы.

А кроме того, что исправил некорректное убиение, не желаешь выдрать из ХТаймера дуратскую подушку безопасности? А то п.2 так и остался в силе.
Честно говоря, я пока не въехал как это работает.
Лучший способ понять что-то самому — объяснить это другому.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16111
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 16.05.2008 (Пт) 0:39

Ты хоть сам понял, что сказал?

Прекрасно. А вот ты походу нет:

Во-первых, кому надо в каждом тике выводить модальное окно? Я лично не могу представить такой надобности. А один-два раза могу вполне.

Где я говорил о создание в каждом тике модального окна?

Во-вторых, нормальные люди ошибки обрабатывают.

Ы.
Во-первых, я в жизни не поверю, что у тебя в коде обрабатываются все возможные ошибки.
Во-вторых, есть целый класс ошибок, которые ты не сможешь обработать.
В-третьих, в обработчике ошибок также может произойти ошибка. Если вышестоящего обработчика нет, произойдёт то, что я описал.
В-четвёртых, если обработчик ошибки выводит сообщение (а он в большинстве случаев делает это), то будет то, чт я описал.


Проблему
Конечно, это самое важное в данном обсуждении. Достойно комментария, занесения в цитаты и коллекцию избранных топиков.

После того, как это слово было написано неправильно 6 раз, я уже не смог удержаться.

Не "приложение замирало", а были бы недоступны юзеру ранее открытые формы. Если нужно - пусть работает.

А не нужно понимать фразу "приложение замирало" в буквальном смысле. Иначе теряется смысл: приложение замрёт - message loop остановится и программа просто не будет работать.


Случается, что мешает. Не помню, что делал, но тоже наткнулся на то, что обычный таймер замирал при выводе модальной формы. Пришлось передать ссылку на вызвавшую форму в модальную и дергать ее процедуру таймером из модальной формы

Я не говорю, что возможность включать/выключать активность таймера во время отображения модальной формы является ненужной возможностью. Очень даже нужной.

Я говорю о принудительном отключении таймера, пока не произошёл возврат из процедуры-обработчика.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 16.05.2008 (Пт) 6:58

Antonariy
Честно говоря, я пока не въехал как это работает.

Во-во, лично для меня в моём коде есть ещё одно неоспоримое преимущество - я его понимаю полностью. А вот ХТаймер не до конца. И есть у меня подознение, что подушка безопасности там вовсе не подушка безопасности, а задний мост. Что-то мне подсказывает, что именно генирация события из класса через вивевентс ненамеренно таким боком вылазит. Хотя конечно, скорее всего я не прав. :lol:

Хакер,
Если ты собираешься исправлять за мной все ошибки орфоргафии, то напоминаю - я дисграфик, и ты скоро задолбаешься. Это не отмазка (я в теме. Скажу тебе что в нашей стране до 80% людей дисграфики в той или иной степени. Издержки "стандартной" методики обучения чтению в начальных классах). Ты ведь тоже наверняка знаешь правило постановки мягкого знака в глаголах на -ся? Пройти проверить твои очипятки? Благо, опыт есть, чужие тетрадки стопками проверял. :lol:

Вспоминается пословица про плохого танцора и его туфли.
Вспоминается метафора про "мочение в сарти..." Или нет, стой, это не метафора и не твоё... У тебя была другая - что-то про спать в туалете.

Для общего развития: чтобы беспощадная ирония, заложенная в метафоре, попадала в цель, мало выразить через неё своё отношение к собеседнику. Нужно ещё, чтобы метафора имела конкретный смысл. Собеседник поставится на место, только если поймёт, что конкретно имелось ввиду под туалетом и какое действие подразумевалось под сном. Мало того - нужно ещё, чтобы и сам ты хотя бы отдалённо представлял, что чего у тебя символизирует. "Потрудитесь объяснить, что на чём стояло"(С).

Почему ты постоянно считаешь, что если я что-то сказал, я обятельно должен привести 10 примеров, выложит сотни сток кода, чтобы дополнить этим сказанное?
Ты никому и ничего не должен. Просто когда ты нагрянешь с очередной метафорой вроде "это всё равно что прыгать с крыльца без парашюта", у меня возникает интерес: что конкретно имеется ввиду под парашютом и под крыльцом? Я свой интерес озвучиваю (можно, надеюсь?). Отвечать или нет - твой выбор (и ты, как правило выбираешь второе). Вообще-то как-то принято в нормальной дискуссии - если говоришь, что всё хреново, поясняешь, что конкретно. А иначе все цветастые метафоры - сотрясение воздуха, даже если глубоко внутри себя ты и прав. Впрочем, никому не запрещено сотрясать воздух.

Можно офтоп ещё пару вопросов?

1. Когда ты высказываешься на какую-то тему, ты хочешь убедить собеседника в том, что говоришь? Тогда приводи аргументы, а не метафоры. Или и аргументы, и метафоры.

2. Или тебе по барабану, "как слово наше отзовётся"? Тогда конечно, можно и не уточнять.

Вот видишь, иногда поснобствовать есть повод и у меня.

Возвращаюсь к баранам:

Мы спорим о безопасности моей обёртки? Она по меньшей мере более безопасна, чем простое Settimer без всякой обёртки (или это тоже черевато каким-нибудь цунами?) Что-то эта офигительная опасность "никого, похоже, кроме тебя, не пугает"
Ну ладно. Представь в что у тебя в обработчике таймера произошла ошибка. Out of memory.
Представил. Очень страшно. И? Если произойдёт этот самый аут, то мало в какой проге не повылазиют глюки. И мало какой юзер оценит, что именно твоя прога мужественно выстояла. Попробуй уронить мой код чем-нибудь менее экзотическим. Мне кажется, сейчас тот случай, когда возразить тебе просто нечего, а признавать это не хочется.

Свойстово, о котором мы спорим - не свойство моего кода, а свойство самого Апи-таймера. И это очень хорошое, очень правильное свойство.

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

А чтобы выполнить из тика что-то длинное, я запускал из него другой таймер, и уже в нём делал что нужно. А таймеры скалдывал на формы, которые время от времени показывались как модальные окна - чтобы те не дохли, когда не надо.

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

1) Для начала надо определиться...
2) Случай, когда itm будет ссылаться ...

Вот за это - спасибо! Когда по делу - всегда приятно тебя послушать.
1. Как оказалось, действительно здесь не для чего. Но может на будущее пригодится. По меньшей мере, встретив этот приём в чужом коде, пойму, что происходит.
2. Тут я спросил довольно путанно. Придумал, как переформулировать: как уничтожить ссылку на объект, созданную таким способом?
Последний раз редактировалось arthur2 16.05.2008 (Пт) 12:29, всего редактировалось 1 раз.
Артур
 
   

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 16.05.2008 (Пт) 9:31

Где я говорил о создание в каждом тике модального окна?
Здесь:
А таймер всё ещё работает. И открывает мессаги, открывает, открывает.
Если это не создание модального окна в каждом тике, никак не ограниченное условиями, то что это?
Ы.

1) В критических местах - всегда.
2) Это означает, что такие ошибки нелься обработать не только в таймере. Зачем тогда о них упоминать как аргумент, что этот таймер - отстой?
3) а)Если обработчик настолько сложен, что есть вероятность возникновения ошибки и она не предусмотрена - автор чудак на букву м. К таймеру это опять же не относится. б) К своему прошлому тесту я добавил обработчик и Err.Raise в обработчике. Произошло ровно тоже самое, как если бы ошибка возникла в коде без обработчика - абсолютно ничего.
А не нужно понимать фразу "приложение замирало" в буквальном смысле.
А а не нужно писать фразы, допускающие двоякое толкование, при обсуждении строго конкретного вопроса. Приостановка выполнения кода и блокирование окон - разные вещи, которые в данном случае должны называться своими именами, а не собирательным термином.
Лучший способ понять что-то самому — объяснить это другому.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 16.05.2008 (Пт) 12:27

Antonariy
Слушай, а как уничтожать ссылку на объект, созданную тем интересным способом? Нужно прогнать через ObjFromPtr Nothing? Или нужно достать через ObjFromPtr ссылку и ей присвоить Nothing? Или нужно как-то по-другому?

Хакер
Кстати, конкретно о механизме обработки ошибок в классах, использующих мой модуль, "как это я"(С) представляю:

1. Произошла ошибка в классе. Кошмар. Отладчик остановился, показывает, куда смотреть.

2. В это время в модуле с чудовищьной неотвратимостью происходят и происходят безчисленые TimeProс. "А таймер всё ещё работает. И открывает мессаги, открывает"... а вот и нет. Потому что:

3. Пока я спокойно изучаю, куда меня ткнул носом отладчик, и пошагово пытаюсь разобраться, класс, в котором произошли все кошмарные ужасы, просто-напросто не доступен для модуля. Там в TimeProc специально перед посылом события классу натянут ремень безопасности (вместо пресловутой подушки), и весь предпологаемый чудовищный напор так и непогашенных таймеров спокойно и мирно продолжает тикать за кулисами, ни чуть не мешая мне спокойно разбираться, что за ошибка произошла.

4. Вариант, когда ужасно кошмарная чудовищная ошибка произошла в экзешнике. Если она не обработана, прога дохнет (но при чём здесь таймер, она бы сдохла при любой необработанной ошибке). Если обработана, то ничего не происходит, кроме этой обработки.

В общем, считаю, что слухи о моих туфлях сильно преувеличены.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16111
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 16.05.2008 (Пт) 12:27

Если ты собираешься исправлять за мной все ошибки орфоргафии, то напоминаю - я дисграфик, и ты скоро задолбаешься. Это не отмазка (я в теме. Скажу тебе что в нашей стране до 80% людей дисграфики в той или иной степени. Издержки "стандартной" методики обучения чтению в начальных классах). Ты ведь тоже наверняка знаешь правило постановки мягкого знака в глаголах на -ся? Пройти проверить твои очипятки? Благо, опыт есть, чужие тетрадки стопками проверял.

Это разные вещи. Я не пишу везде ться и тся неправильно. Кроме того, пропустить букву проще, чем вставить лишнюю. Кроме того, мои сообщения содержат ошибки в большинстве случаев потому, что я напишу предложение, а затем его корректирую, меняя до неузнаваемости. Поэтому слова не всегда согласуются, в частности по окончаниями. Ты же пишешь слово проблемма постоянно.

Это уж больлно смахивает на то, что человек не знает, как пишет это слово. Т.е. сомневается, и под влиянием таких слов как лемма, клемма, дилемма пишет удовенную М и здесь.

1. Когда ты высказываешься на какую-то тему, ты хочешь убедить собеседника в том, что говоришь? Тогда приводи аргументы, а не метафоры. Или и аргументы, и метафоры.


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

Я считаю, что если я достаточно автиритетен для человека, что он мочла согласится с моим мнением, то доказательства не нужно писать.
Если же человек, не считает, что Хакер - этот тот, кто пишет всякую чушь, и его словам нельзя верить просто так, то пусть считает дальше, ему же потом хуже будет от использования дрянного метода.

Попробуй уронить мой код чем-нибудь менее экзотическим.

Звучит так, как будто ты гуру надёжного кода.

Мне кажется, сейчас тот случай, когда возразить тебе просто нечего, а признавать это не хочется.

Мне кажется, что тебе не стоит говорить со мной в подобном тоне :? .

Вот за это - спасибо! Когда по делу - всегда приятно тебя послушать.

Это всё походит на тот случай, когда человека ценят исключительно как потенциально полезный объект. Типа: Хакер, сам ты - говно (извиняюсь), и мнение твоё - говно, но знаешь, ты крут тогда, когда даёшь код, который никто другой кроме тебя не может дать.

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

У меня отпадает всякое желание тебе, arthur2, помогать. Один раз уже почти отпало, но восстановилось. Сейчас упадёт окончательно.

Стоп! Придумал, как спросить: как уничтожить ссылку на объект, созданную таким способом?

1) Каким таким?
2) Каким бы образом ты не был создан объект, уничтожение ссылки происходит одинаково. Вызов IDispatch::Release у объекта, на который ссылалась ссылка и присвоение ссылке нуля.

Antonariy
Antonariy писал(а):Во-первых, кому надо в каждом тике выводить модальное окно? Я лично не могу представить такой надобности.

Хакер писал(а):Где я говорил о создание в каждом тике модального окна?

Antonariy писал(а):Здесь:
А таймер всё ещё работает. И открывает мессаги, открывает, открывает.
Если это не создание модального окна в каждом тике, никак не ограниченное условиями, то что это?


Путаешься...
Ты меня спросил, кому надо (по моему мнению, словно я говорил что кому-то именно "надо", кто-то именно хочет сам выводить мессадж) в каждом тике выводить модальное окно.

Когда тебе сказал, что я не говорил, что кому-то это может быть нужно, ты мне возразил цитированием моей фразы "А таймер всё ещё работает. И открывает мессаги, открывает, открывает.".

Тебе не очевидно хотя бы то, что мессаги, которые таймер "открывает, открывает" будут выводиться не потому, что это кому-то хотелось или было нужным, а потому, что ошибка произошла, и никто не спрашивает у вас, хотите ли вы вывод мессаги.

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

2) Это означает, что такие ошибки нелься обработать не только в таймере. Зачем тогда о них упоминать как аргумент, что этот таймер - отстой?

Это действительно означает, что такие ошибки обработать нельзя не только в таймере, не спорю. Но такая ошибка в обычном таймере - это MsgBox и завершение проги. А та же ошибка в таймере без самоконтроля - это десятки MsgBox-ов в секунду, появляющиеся с дикой интенсивностью, которые пользователь просто не сможет закрыть. Которые сожрут ресурсы и затормозят работу системы настолько, что вообще вряд ли получится выйти из этой ситуации.

Кроме сообщений, о которых много говорили, вот тебе ещё и другой пример: Таймер с интервалом 100 мс, открывает файл, читает первую половину файла, делает DoEvents, читает вторую половину, закрывает файл. Если по какой-либо причине оранжевые действия займут больше 100 мс. - тик-хендлинг поставится в очередь сообщений. И после того, как эти оранжевые действия завершатся, вызов DoEvents приведёт к обработке тика, поставленного в очередь. Таким образом DoEvents инициирует запуск обработки нового типка, а обработчик нового типка (если оранжевый код опять не уложится в 100 мс) вызовет третий фрейм рекурсии.

Если частота опаздывания будет небольшой, то просто не будет возврата в синеку коду первого фрейма. Если же она большая, будет переполнение стека. Которая будет появляться без всякой закономерности. А крмое того, после того как она произойдёт, будет ещё каждый 100 мс высплывать сообщение Out of space stack, пока рубежная страница стека не кончится, и приложение не будет убито.





а)Если обработчик настолько сложен, что есть вероятность возникновения ошибки и она не предусмотрена - автор чудак на букву м.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 16.05.2008 (Пт) 13:39

Путаешься...
Еще бы, ты никогда не говоришь менее, чем двусмысленно. Достала меня эта словесная эквилибристика.

Тебе не очевидно хотя бы то, что мессаги, которые таймер "открывает, открывает" будут выводиться не потому, что это кому-то хотелось или было нужным, а потому, что ошибка произошла, и никто не спрашивает у вас, хотите ли вы вывод мессаги.
Мне пока что очевидно только то, что ты игнорируешь все, что я писал про Err.Raise. Ну не выскакивает в exe системное сообщение об ошибке, хоть тресни.

Слушай, а как уничтожать ссылку на объект, созданную тем интересным способом?
По пунктам.
1) В вб объект создается как правило через New или CreateObject, способами совершенно неинтересными и тривиальными.
2) Объект может храниться только в объектной переменной или коллекции.
3) ObjPtr возвращает адрес памяти (типа Long) в котором хранится ссылка (адрес VTABLE).
4) ObjFromPtr присваивает переменной ссылку на тот же объект, получая ее из адреса. ObjFromPtr ничего не создает.

Поэтому "как уничтожать ссылку на объект, полученную тем интересным способом" - точно так же, как и любую другую объектную ссылку - Nothing.
Как уничтожить сам объект - уничтожить последнюю ссылку.
Как уничтожить последнюю ссылку, если объектная переменная находится вне области видимости, но есть адрес - CopyMemory address, 0, 4.

Зачем вообще пользоваться ручным COM'ом - чтобы не плодить лишние ссылки, которые потом может быть будет не очень удобно удалять.
Последний раз редактировалось Antonariy 16.05.2008 (Пт) 13:54, всего редактировалось 1 раз.
Лучший способ понять что-то самому — объяснить это другому.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16111
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 16.05.2008 (Пт) 13:52

Мне пока что очевидно только то, что ты игнорируешь все, что я писал про Err.Raise. Ну не выскакивает в exe системное сообщение об ошибке, хоть тресни.

Да. Там речь идёт о каких-то тестах. О каких тестах? Я не понимаю, о чем речь.

Объект может храниться только в объектной переменной или коллекции.

Объект не может храниться ни там ни там. Храниться в объектных переменных и коллекциях могут ссылки на интерфейсы объектов.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 16.05.2008 (Пт) 14:01

Да. Там речь идёт о каких-то тестах. О каких тестах? Я не понимаю, о чем речь.
Или не хочешь понимать? Если бы ты хотя бы смотрел кирпич, тебе было бы понятно.
Объект не может храниться ни там ни там. Храниться в объектных переменных и коллекциях могут ссылки на интерфейсы объектов.
Ведь так и знал, что придерешься :roll:
Не важно, что там хранится технически, важно, что без привязки к этим сущностям объект в vb существовать не может.
Лучший способ понять что-то самому — объяснить это другому.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1598
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 16.05.2008 (Пт) 14:05

Про очипятки повторю: ты просто не в теме. А я этот вопрос изучал (в отличии от бейсика). Проблеммы возникают по инерции из программ, дилемм и иже с ними. Часто это означает не то, что человек не знает, как слово пишется, а то, что он пишет его спонтанно, неконтролируемо. А ещё я часто пишу б вместо д и з вместо ж (в том числе и ручкой), попадаются у меня с завидным постоянством "зделать", "сного" и пр. У меня друг-одноклассник с так называемой врождённой граммотностью. Он всегда мне ошибки в диктантах проверял, а я ему всякие грамматические разборы делал.

Я считаю, что если я достаточно автиритетен для человека, что он мочла согласится с моим мнением, то доказательства не нужно писать.
Считай, кто ж тебе мешает. В программировании ты для меня несомненный авторитет. Но "не сотвори себе кумира"- гуру тоже ошибаются. И - как и простые смертные - они тоже не любят своих ошибок признавать, тем более когда были столь категоричны. Надувание щёк не убеждает - убеждают довыды. И кстати, не твоё ли кредо - ни кому не верить на слово и до всего доходить самому? А я и в школе с преподами спорил, и в институте. Причём - вот совпадение - почему-то именно с теми, кто для меня был авторитетом. Странно, правда? Правда, и среди авторитетных преподов попадаются те, кому не нравится, что на слово им не верят. Это, кстати, и называется снобизм.

Мне кажется, что тебе не стоит говорить со мной в подобном тоне
А мне почему-то кажется, что тебе самому не мешало бы обращать внимание на свой тон. Ты не напомнишь, где я позволял себе в отношении кого бы то ни было скабрезные и туалетные метафоры? И не досочиняй за меня моё к тебе отношение, тем более в таких выражениях. "Юпитер, ты сердишься?" Помнишь, как дальше?

Таймер с интервалом 100 мс, открывает файл, читает первую половину файла, делает DoEvents, читает вторую половину, закрывает файл.
Пример какой-то вымученый. Ну ладно, в такой ситуации апи-таймер не годится, и что? А в другой - очень даже годится. Используя твою логику, и так любимый тобой язык метафор (в котором ты плаваешь), можно сказать, что "туфельки у вас дрянь, потому что в них по крышам лазить не удобно". Если поднапречься, можно, наверное, и для стандартного таймера придумать ситуацию, после которой винду переставлять придётся.
Артур
 
   

След.

Вернуться в Кирпичный завод

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

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

    TopList