Doevents своими руками

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

Re: Doevents своими руками

Сообщение arthur2 » 22.04.2010 (Чт) 21:06

Хакер писал(а):Принципиальные грабли: при обработке какого-то сообщения обработчик породит свой ML, который случайно обработает твоё таймерное событие

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

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

Re: Doevents своими руками

Сообщение Хакер » 22.04.2010 (Чт) 21:10

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

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

Re: Doevents своими руками

Сообщение arthur2 » 25.04.2010 (Вс) 12:23

Хакер писал(а):Смысл в своём ML — затормозить выполнение кода, заблокировать его внутри нужной процедуры пока не произойдёт что-то.
Хакер писал(а):Принципиально отказаться от дурацкой архитектуры.
Тогда каким другим способом "затормозить выполнение кода", не замораживая при этом UI?

Кстати, ты же и предложил идею самим скормить гету событие таймера:
Хакер писал(а):Ну ладно, раскрою: можно запустить таймер, который сработает через 100 мс и пришёл сообщение и вызвать GetMessage.


Хакер писал(а):Принципиальные грабли: при обработке какого-то сообщения обработчик породит свой ML, который случайно обработает твоё таймерное событие. Тогда тебе придётся нового таймерного события, но и его может кто-нибудь съесть
Это решить, как оказалось, совсем просто :)
Код: Выделить всё
Sub mySleep(ByVal dwMillisecond As Long)
    Dim idTm As Long, MSG As MSG
    Dim endInterval As Long, tmNow As Long
    On Error GoTo errH
    endInterval = GetTickCount + dwMillisecond
    On Error GoTo 0
   
'   idTm = SetTimer(0&, 0&, dwMillisecond, AddressOf TimerProc)
    idTm = SetTimer(0&, 0&, dwMillisecond, 0&)
   
    Do
      GetMessage MSG, 0&, 0&, 0&
      TranslateMessage MSG
      DispatchMessage MSG
      tmNow = GetTickCount
'      MSG.Time не годится, потому что за время обработки DispatchMessage интервал может уже и закончится
'      If MSG.Time < 0 Then If endInterval >= 0 Then Exit Do
'      If MSG.Time >= endInterval Then Exit Do

      If tmNow < 0 Then If endInterval >= 0 Then Exit Do '
      If tmNow >= endInterval Then Exit Do
    Loop
   
    KillTimer 0&, idTm
Exit Sub
errH:
   If Err.Number = 6 Then 'переполнение
     endInterval = &H80000000 + dwMillisecond - (&H7FFFFFFF - GetTickCount)
   End If
   Resume Next
End Sub

Съесть наш таймер могут только внутри нашего DispatchMessage, но это нам уже по барабану, потому что для выхода мы теперь ориентируемся не на MSG.Time, а на GetTickCount уже после обработки сообщения.

Остались грабли?
Артур
 
   

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

Re: Doevents своими руками

Сообщение Хакер » 25.04.2010 (Вс) 16:19

Тогда каким другим способом "затормозить выполнение кода", не замораживая при этом UI?

Зачем вообще тормозить выполнение кода?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

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

Re: Doevents своими руками

Сообщение arthur2 » 25.04.2010 (Вс) 16:45

arthur2 писал(а):Остались грабли?
Артур
 
   

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

Re: Doevents своими руками

Сообщение Хакер » 25.04.2010 (Вс) 16:49

Я тоже так умею:

Зачем вообще тормозить выполнение кода?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

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

Re: Doevents своими руками

Сообщение arthur2 » 25.04.2010 (Вс) 17:32

arthur2 писал(а):И всё-таки - четвёртый раз: каков на предмет наличия граблей этот код:
Хакер писал(а):В mySleep много граблей.
arthur2 писал(а):Ну же???
Хакер писал(а):Предполагалось, что ты напряжёшь мозги и сам проанализируешь. А я уж поправлю. Не-а?
arthur2 писал(а):вот проба устранить те грабли, которые понял
Хакер писал(а):Код оценю завтра.
(20.04.2010 (Вт))

arthur2 писал(а):Остались грабли?
Артур
 
   

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

Re: Doevents своими руками

Сообщение Хакер » 25.04.2010 (Вс) 17:34

Обрати внимание на «и всё-таки» в начале первой своей цитаты. Оно там у тебя неспроста.

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

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

Re: Doevents своими руками

Сообщение arthur2 » 25.04.2010 (Вс) 17:48

Хакер писал(а):Принципиально отказаться от дурацкой архитектуры.

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

Я готов отказаться архитектуры, если она дурацкая... но сначала нужно либо удалить грабли, либо доказать их неудаляемость.

Итак, остались ещё грабли? Если уже не осталось, то можем обсудить и дурацкость архитектуры :D
Артур
 
   

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

Re: Doevents своими руками

Сообщение Хакер » 25.04.2010 (Вс) 18:32

Не обнаружена логика.

Какой смысл устранять грабли в коде, расчитанным на архитектуру, от которой всё равно нужно отказаться?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

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

Re: Doevents своими руками

Сообщение arthur2 » 25.04.2010 (Вс) 18:37

забудь
Артур
 
   

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

Re: Doevents своими руками

Сообщение Хакер » 25.04.2010 (Вс) 18:38

О чём?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

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

Re: Doevents своими руками

Сообщение arthur2 » 25.04.2010 (Вс) 18:39

да так - задолбался переспрашивать, считай, что я ничего и не спрашивал.

Твой и мой перфекционизм лежат в разных плоскостях
Артур
 
   

Filyus
Обычный пользователь
Обычный пользователь
 
Сообщения: 81
Зарегистрирован: 07.07.2011 (Чт) 11:54

Re: Doevents своими руками

Сообщение Filyus » 26.02.2013 (Вт) 8:56

Извиняюсь, что поднимаю столь старую тему, но написал достаточно стабильную альтернативную версию DoEvents. Не зависает при переходе в режим отладки и при выходе из программы.
Оригинальный DoEvents вызывается только единожды - перед переходом в режим отладки.
Пока не знаю зачем, но, кажется, не зря. По скорости работы разницы не заметил.
Тема, с которой взят код для теста: viewtopic.php?f=1&t=44295&start=0
Код: Выделить всё
Public Function DoEvents2() As Boolean
  Dim MSG As MSG, Ret As Long
  DoEvents2 = True
  While PeekMessage(MSG, 0, 0, 0, PM_REMOVE)
    TranslateMessage MSG
    'your code before here
    DispatchMessage MSG
    If IsExit = True Then
      DoEvents2 = False
      Exit Function
    End If
    If IsIDE = True Then
      If EbMode <> 1 Then
        DoEvents
      End If
    End If
    'your code after here
  Wend
End Function

Код: Выделить всё
Private Sub Form_Unload(Cancel As Integer)
  IsExit = True
End Sub

Код: Выделить всё
Public Function IsIDE() As Boolean
  On Error Resume Next
  Debug.Print 0 / 0
  IsIDE = Err.Number
End Function
Вложения
DoEvents2.rar
(7.01 Кб) Скачиваний: 120

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 26.02.2013 (Вт) 10:37

Что за привычка писать If Smth = True Then?

Filyus писал(а):
Код: Выделить всё
Public Function IsIDE() As Boolean
  On Error Resume Next
  Debug.Print 0 / 0
  IsIDE = Err.Number
End Function

Хакер где-то писал как хорошо сделать проверку на IDE при помощи ByRef-параметра.
А про эту у меня есть подозрение, что она ещё и не всегда работает...

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

Re: Doevents своими руками

Сообщение Хакер » 26.02.2013 (Вт) 11:14

Qwertiy писал(а):Хакер где-то писал как хорошо сделать проверку на IDE при помощи ByRef-параметра.

Ничего себе где-то... viewtopic.php?f=68&t=42654
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Filyus
Обычный пользователь
Обычный пользователь
 
Сообщения: 81
Зарегистрирован: 07.07.2011 (Чт) 11:54

Re: Doevents своими руками

Сообщение Filyus » 26.02.2013 (Вт) 11:58

А по делу что-нибудь?
Такой IsIDE здесь использован только для простоты. Он всегда работает, но сам я обычно использую условную компиляцию.
За ссылку - спасибо. Не знал, что компилятор у VB такой умный, хотя это ещё нужно проверить.
Последний раз редактировалось Filyus 26.02.2013 (Вт) 12:41, всего редактировалось 2 раз(а).

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

Re: Doevents своими руками

Сообщение Хакер » 26.02.2013 (Вт) 12:18

Filyus писал(а):Не знал, что компилятор у VB такой умный, хотя это ещё нужно проверить.

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

Filyus
Обычный пользователь
Обычный пользователь
 
Сообщения: 81
Зарегистрирован: 07.07.2011 (Чт) 11:54

Re: Doevents своими руками

Сообщение Filyus » 26.02.2013 (Вт) 12:40

Хакер писал(а):
Filyus писал(а):Не знал, что компилятор у VB такой умный, хотя это ещё нужно проверить.

Проверить нужно? Не доверяешь мною написанному что-ли?

Доверяю, но не помешало бы проверить что будет при объявлении переменной в модуле. Что будет компилироваться, а что - нет.
Ещё бы не помешало проверить - будут ли компилироваться функции в ветке False, которые указаны в AddressOf.
А вообще, лучше add-in написать, который будет глобальную константу устанавливать, если вам так важны скорость и удобство IsIDE.
Последний раз редактировалось Filyus 26.02.2013 (Вт) 12:44, всего редактировалось 1 раз.

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

Re: Doevents своими руками

Сообщение Хакер » 26.02.2013 (Вт) 12:42

Filyus писал(а):Доверяю, но не помешало бы проверить что будет при объявлении переменной в модуле.

Фигня будет. Зачем объявлять переменную в модуле?
И Add-in абсолютно ничем не лучше. Это переход из мира, где ваш проект скомпилируется на любой машине у абсолютного кого угодно в мир, где ваш проект скомпилируется только на вашей личной машине и только у тех немногих, кого вы уломаете установить ваш Add-in.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 26.02.2013 (Вт) 12:45

Хакер писал(а):Ничего себе где-то... viewtopic.php?f=68&t=42654

Мне было лень искать :)

Filyus писал(а):Такой IsIDE здесь использован только для простоты. Он всегда работает

Но ведь берётся Err.Number. Т. е. без IDE будет такая функция:
Код: Выделить всё
Public Function IsIDE() As Boolean
  On Error Resume Next
  IsIDE = Err.Number
End Function
Почему невозможна ситуация, что кто-то ещё установит код ошибки, а тут просто будет True, т. к. его никто не очистил?

Filyus
Обычный пользователь
Обычный пользователь
 
Сообщения: 81
Зарегистрирован: 07.07.2011 (Чт) 11:54

Re: Doevents своими руками

Сообщение Filyus » 26.02.2013 (Вт) 12:54

Хакер писал(а):Фигня будет. Зачем объявлять переменную в модуле?
И Add-in абсолютно ничем не лучше. Это переход из мира, где ваш проект скомпилируется на любой машине у абсолютного кого угодно в мир, где ваш проект скомпилируется только на вашей личной машине и только у тех немногих, кого вы уломаете установить ваш Add-in.

Затем, что мне не охота эту переменную везде объявлять.
Код нужен прежде всего для себя. С другими я им редко делюсь. Мне важнее быстрый, но хороший результат, ну и код достаточно красивый, конечно) Те, кто разделяют мою точку зрения, скачают add-in и будут им пользоваться.

Filyus
Обычный пользователь
Обычный пользователь
 
Сообщения: 81
Зарегистрирован: 07.07.2011 (Чт) 11:54

Re: Doevents своими руками

Сообщение Filyus » 26.02.2013 (Вт) 12:54

Qwertiy писал(а):
Filyus писал(а):Такой IsIDE здесь использован только для простоты. Он всегда работает

Но ведь берётся Err.Number. Т. е. без IDE будет такая функция:
Код: Выделить всё
Public Function IsIDE() As Boolean
  On Error Resume Next
  IsIDE = Err.Number
End Function
Почему невозможна ситуация, что кто-то ещё установит код ошибки, а тут просто будет True, т. к. его никто не очистил?

On Error ... - очищает код ошибки.

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

Re: Doevents своими руками

Сообщение arthur2 » 26.02.2013 (Вт) 21:05

Filyus писал(а):но написал достаточно стабильную альтернативную версию DoEvents


А чем нестабильна эта? То есть, может она и действительно нестабильна, но я не замечал :)
Код: Выделить всё
Sub myDoEvents()

  Dim MSG As MSG
  Do While PeekMessage(MSG, 0&, 0&, 0&, PM_REMOVE)
    TranslateMessage MSG
    DispatchMessage MSG
  Loop

End Sub
Артур
 
   

Filyus
Обычный пользователь
Обычный пользователь
 
Сообщения: 81
Зарегистрирован: 07.07.2011 (Чт) 11:54

Re: Doevents своими руками

Сообщение Filyus » 27.02.2013 (Ср) 12:19

Я же писал...
Filyus писал(а):Не зависает при переходе в режим отладки и при выходе из программы..

Это про мой вариант. То есть если в твоём коде попытаться закрыть форму, то форма переоткроется, а если нажать Ctrl+Break, то вообще зависнет.

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

Re: Doevents своими руками

Сообщение arthur2 » 28.02.2013 (Чт) 11:17

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

Filyus
Обычный пользователь
Обычный пользователь
 
Сообщения: 81
Зарегистрирован: 07.07.2011 (Чт) 11:54

Re: Doevents своими руками

Сообщение Filyus » 06.03.2013 (Ср) 8:37

arthur2 писал(а):Нельзя ли пояснить ситуацию кодом? Что-то не могу представить, как пытаться закрыть форму во время выполнения этого кода. Про Енд вообще молчу, ибо без крайней необходимости вообще им не пользуюсь.

Код я выкладывал в архиве выше. В цикле делается постоянная отрисовка, поэтому и закрыть форму придётся во время его выполнения.

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

Re: Doevents своими руками

Сообщение arthur2 » 06.03.2013 (Ср) 11:43

Пардон, но зависание у тебя не там, где надо. Если ты делаешь аналог Doevents-a, то ни какого выхода из него не нужно. Выход из цикла нужно делать там, где ты этот цикл организуешь.

Для твоего кода, что бы он ни значил :) :

Код: Выделить всё
Private Sub Form_Load()
  Move Left, Top, Width - Screen.TwipsPerPixelX * (ScaleWidth - WW), Height - Screen.TwipsPerPixelY * (ScaleHeight - HH)
  pic.Move 0, 0, WW, HH
  Show

  ReDim cBuf(WW - 1, HH - 1) As Long
  With bi32BitInfo.bmiHeader
    .biBitCount = 32
    .biPlanes = 1
    .biSize = Len(bi32BitInfo.bmiHeader)
    .biWidth = WW
    .biHeight = -HH
    .biSizeImage = 4 * (WW * HH)
  End With

  Dim MSG As MSG, Ret As Long
  Do
    myDoEvents
    If IsExit Then Exit Do
    Render
    FPS = FPS + 1
  Loop
'  While DoEvents2 'DoEvents
'    Render
'    FPS = FPS + 1
'  Wend
End Sub

Код: Выделить всё
Sub myDoEvents()

  Dim MSG As MSG
  Do While PeekMessage(MSG, 0&, 0&, 0&, PM_REMOVE)
    TranslateMessage MSG
    DispatchMessage MSG
  Loop

End Sub

По-моему, работает вполне стабильно :)
Артур
 
   

Filyus
Обычный пользователь
Обычный пользователь
 
Сообщения: 81
Зарегистрирован: 07.07.2011 (Чт) 11:54

Re: Doevents своими руками

Сообщение Filyus » 06.03.2013 (Ср) 12:44

arthur2 писал(а):По-моему, работает вполне стабильно :)

Ну если без отладки, тогда согласен.

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

Re: Doevents своими руками

Сообщение arthur2 » 06.03.2013 (Ср) 14:00

Ну вот, и я поймал эту нестабильность. Ага, теперь согласен, для отладки таки нужен EbMode
Код: Выделить всё
Sub myDoEvents()
  Dim WE_ARE_IN_IDE As Boolean:  Debug.Assert MakeTrue(WE_ARE_IN_IDE) 'фишка от хакера
 
  Dim MSG As MSG
  Do While PeekMessage(MSG, 0&, 0&, 0&, PM_REMOVE)
    If WE_ARE_IN_IDE Then If EbMode = 2 Then DoEvents: Exit Sub
 
    TranslateMessage MSG
    DispatchMessage MSG
  Loop




Собственно, получилось почти как и у тебя, за исключением того, что выбросил аварийный выход и заменил определение ИДЕ фишкой от Хакера.
Артур
 
   

Пред.След.

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

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

Сейчас этот форум просматривают: AhrefsBot, Google-бот, Mail.ru [бот], SemrushBot и гости: 55

    TopList