Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   Таймер (http://forum.oszone.net/showthread.php?t=221775)

winipox 29-11-2011 18:02 1805814

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

Iska 29-11-2011 21:10 1805938

winipox, AutoIt — однопоточное приложение. Так что и делайте два макроса. Либо согласитесь на то, что при работе процедуры обработки события тайминга основное приложение будет временно «заморожено».

madmasles 30-11-2011 00:09 1806065

Цитата:

Цитата Iska
основное приложение будет временно «заморожено». »

Смотря что будет делать основное приложение. В некоторых случаях можно использовать _Timer_SetTimer().

Iska 30-11-2011 02:48 1806140

Цитата:

Цитата madmasles
В некоторых случаях можно использовать _Timer_SetTimer(). »

И…? Поясните, это сделает возможным в одном скрипте AutoIt исполнение процедуры и, одновременно, продолжение исполнения основного кода скрипта?

madmasles 30-11-2011 11:22 1806300

Iska,
Пример. Одновременно работают основной цикл, часы, прогресс и его строковое значение. При этом можно прервать цикл или выйти из программы (если выход во время работы цикла, то код выхода 1).
Код:

#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <Timers.au3>
#include <GuiStatusBar.au3>
#include <ProgressConstants.au3>
#include <EditConstants.au3>
#include <MenuConstants.au3>

Global $nMemo, $hStatusBar, $nProgress, $iPercent = 0, $direction = 1, $aParts[3] = [100, 300, -1], _
        $nBtn_start, $nBtn_stop, $iTimerProgress, $iStart, $iTimeOut = 60000, $fWork, $fStop

$hGUI = GUICreate('Test Func _Timer_SetTimer()', 400, 320, -1, -1, -1, $WS_EX_TOOLWINDOW)
$nMemo = GUICtrlCreateEdit('', 2, 32, 396, 226, BitOR($WS_HSCROLL, $WS_VSCROLL, $ES_READONLY))
GUICtrlSetFont($nMemo, 9, 400, 0, 'Courier New')
$nBtn_start = GUICtrlCreateButton('Start', 70, 265, 100, 25)
$nBtn_stop = GUICtrlCreateButton('Stop', 215, 265, 90, 25)
GUICtrlSetState(-1, $GUI_DISABLE)
$hStatusBar = _GUICtrlStatusBar_Create($hGUI, $aParts)
_GUICtrlStatusBar_SetText($hStatusBar, @TAB & StringFormat('%02d:%02d:%02d', @HOUR, @MIN, @SEC), 2)
$nProgress = GUICtrlCreateProgress(0, 0, -1, -1, $PBS_SMOOTH)
_GUICtrlStatusBar_EmbedControl($hStatusBar, 1, GUICtrlGetHandle($nProgress))
GUICtrlSetState($nProgress, $GUI_HIDE)
GUISetState()
GUIRegisterMsg($WM_COMMAND, 'WM_COMMAND')
GUIRegisterMsg($WM_SYSCOMMAND, 'WM_SYSCOMMAND')
_Timer_SetTimer($hGUI, 1000, '_UpdateStatusBarClock')

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $nBtn_start
            $fWork = True
            $fStop = False
            $iStart = TimerInit()
            GUICtrlSetData($nProgress, 0)
            GUICtrlSetState($nProgress, $GUI_SHOW)
            GUICtrlSetState($nBtn_stop, $GUI_ENABLE)
            GUICtrlSetState($nBtn_start, $GUI_DISABLE)
            GUICtrlSetData($nMemo, '')
            $iTimerProgress = _Timer_SetTimer($hGUI, 100, '_UpdateProgressBar')
            _BasicCycle()
    EndSwitch
WEnd

Func _BasicCycle()
    ;основной цикл для примера
    Local $i_Count = 0, $s_Mess
    MemoWrite('Основной цикл будет работать ' & StringFormat('%d сек.', $iTimeOut / 1000) & @CRLF)
    MemoWrite('Его можно прервать, нажав кнопку "Stop".' & @CRLF)
    MemoWrite('~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~' & @CRLF)
    MemoWrite('Работает основной цикл.' & @CRLF)
    While 1
        $i_Count += 1
        $s_Mess = $i_Count & ','
        If Not Mod($i_Count, 12) Then $s_Mess &= @CRLF
        MemoWrite($s_Mess)
        Sleep(Random(100, 500, 1))
        If Not $fWork Then ExitLoop
        If $fStop Then ExitLoop
    WEnd
    _Timer_KillTimer($hGUI, $iTimerProgress)
    GUICtrlSetState($nProgress, $GUI_HIDE)
    GUICtrlSetState($nBtn_stop, $GUI_DISABLE)
    GUICtrlSetState($nBtn_start, $GUI_ENABLE)
    If $fStop Then
        MemoWrite(@CRLF & '~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~' & @CRLF)
        MemoWrite('Основной цикл прерван пользователем.' & @CRLF)
    Else
        MemoWrite(@CRLF & '~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~' & @CRLF)
        MemoWrite('Основной цикл закончен по таймауту.' & @CRLF)
    EndIf
EndFunc  ;==>_BasicCycle

Func _UpdateStatusBarClock($hWnd, $Msg, $iIDTimer, $dwTime)
    #forceref $hWnd, $Msg, $iIDTimer, $dwTime
    _GUICtrlStatusBar_SetText($hStatusBar, @TAB & StringFormat('%02d:%02d:%02d', @HOUR, @MIN, @SEC), 2)
EndFunc  ;==>_UpdateStatusBarClock

Func _UpdateProgressBar($hWnd, $Msg, $iIDTimer, $dwTime)
    #forceref $hWnd, $Msg, $iIDTimer, $dwTime
    Local $s_Mess, $i_Diff
    $i_Diff = TimerDiff($iStart)
    $iPercent = Int(100 * $i_Diff / $iTimeOut)
    $s_Mess = StringFormat('%.1f сек(%02d%)', $i_Diff / 1000, $iPercent)
    If $iPercent = 100 Then
        $fWork = False
        $s_Mess = StringFormat('%.1f сек(%02d%)', $iTimeOut / 1000, $iPercent)
    EndIf
    GUICtrlSetData($nProgress, $iPercent)
    _GUICtrlStatusBar_SetText($hStatusBar, @TAB & $s_Mess, 0)
EndFunc  ;==>_UpdateProgressBar

Func MemoWrite($s_Message)
    GUICtrlSetData($nMemo, $s_Message, 1)
EndFunc  ;==>MemoWrite

Func WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $nID = BitAND($wParam, 0xFFFF)
    Switch $nID
        Case $SC_CLOSE
            If $fWork Then Exit 1
            Exit
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc  ;==>WM_SYSCOMMAND

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $nID = BitAND($wParam, 0xFFFF)
    Switch $nID
        Case $nBtn_stop
            $fStop = True
            $fWork = False
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc  ;==>WM_COMMAND


Creat0R 30-11-2011 17:43 1806647

winipox,
Предупреждение за нарушение правил форума, пункт 2.7 и пункт 3.19:

Цитата:

2.7: В заголовке темы обязательно обозначайте название предмета, которого касается вопрос, а в теле сообщения максимально подробно опишите проблему (приведите аппаратную/программную конфигурацию, а также изложите ситуацию, в которой возникает проблема)...
Подробнее о принципах создания тем читайте в этом документе и Правилах форумов.

3.19: Запрещается... Создавать темы, имеющие неинформативные или состоящие из заглавных букв заголовки (например, "Помогите!", "HELP!", "У меня проблема"). Такие темы будут закрыты или перенесены в Тест-форум. Если вы хотите вернуть перенесенную тему обратно, пока ее не закрыли в Тест-форуме, измените ее заголовок на осмысленный и напишите об этом в теме.
Переименуйте пожалуйста тему (Как переименовать свою тему?).

Iska 30-11-2011 22:53 1806870

madmasles, Вы меня не поняли. Добавьте, например, в обработку вычиcления пообъёмнее, даже хотя бы симулировать банально Sleep()'ом:
Код:

Func _UpdateProgressBar($hWnd, $Msg, $iIDTimer, $dwTime)
        …
        Sleep(5000)
EndFunc  ;==>_UpdateProgressBar

и что получится с основным циклом? Понимаете меня? То есть, это:
Цитата:

Цитата Iska
Либо согласитесь на то, что при работе процедуры обработки события тайминга основное приложение будет временно «заморожено». »


madmasles 30-11-2011 23:53 1806910

Iska,
Я Вас и сейчас не понимаю. Что значит вычисления пообъёмнее? Пример? Зачем в функцию _UpdateProgressBar() добавлять Sleep(5000)?

Iska 01-12-2011 01:56 1806952

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

madmasles 01-12-2011 08:51 1807025

Цитата:

Цитата Iska
для того, чтобы показать, что при работе процедуры выполнение основного кода скрипта будет приостановлено до её завершения. »

Зачем? Код же работает.

PS
С помощью Sleep() можно много чего испортить, например:
Код:

#include <GuiConstantsEx.au3>

$hGui = GUICreate('Test')
$nBtn = GUICtrlCreateButton('Test', 20, 20)
GUISetState()
While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $nBtn
            MsgBox(64, 'Info', 'Click', 0, $hGui)
    EndSwitch
    ;Sleep(1000);раскомментируйте строку и скрипт не будет работать.
WEnd


Iska 01-12-2011 16:27 1807348

Цитата:

Цитата madmasles
Зачем? Код же работает. »

Работает. Но не независимо. Что я и пытался показать на примере.

Цитата:

Цитата madmasles
С помощью Sleep() можно много чего испортить, например: »

Это не тот пример ;). Я же задерживал исполнение процедуры обработки — и оказывалось, что основной код во время работы процедуры — не работает, а «стоит» и «ждёт» окончания обработки.

Смотрите:
Цитата:

Цитата winipox
требуется таймер, который будет выполняться в полной независимости от остального кода. … Таймер должен работать независимо от самого скрипта, ровно как 2 макроса [скрипт] и [таймер] единовременно. »

Цитата:

Цитата madmasles
Одновременно работают основной цикл, часы, прогресс и его строковое значение. »

Достаточно добавить в процедуру обработки таймера какие-либо массивные вычисления, долгий код (Sleep() — это только для примера), и сразу становится ясно, что никакой одновременной, никакой независимой друг от друга работы основного кода и процедуры обработки таймера нет. О чём я и написал во втором посте темы. О чём явно написано в другом примере — AdlibRegister:
Цитата:

The adlib function should be kept simple as it is executed often and during this time the main script is paused.
Вы просто меня не поняли ;).

Автор что-то молчит. Я-то думаю, что для его целей наверняка хватит и существующей технологии квази-независимой обработки.


Время: 00:47.

Время: 00:47.
© OSzone.net 2001-