Что нового

[Интеракция] Пробуждение скрипта после долгого сна и взаимодействие с пользователем

Medved

Новичок
Сообщения
27
Репутация
0
Вопрос теоретического характера. Допустим, есть скрипт с управлением горячими клавишами, у которого есть период долгого сна (5 минут в примере), после которого он должен сделать какие-то действия. Понятно, что пользователь за время сна может снять скрипт с паузы. Я ставлю дополнительную проверку на то, что скрипт все еще в режиме паузы по окончанию сна. Вроде работает, но не совсем понимаю особенности взаимодействия параллельно запущенных обработчиков паузы.

На каком этапе спящий обработчик понимает, что глобальная переменная поменяла свое значение и требуется выйти из всех его циклов? Более того, за время его сна, скрипт может быть снят и поставлен на паузу пользователем заново. Однако спящий обработчик как-то это понимает и все равно завершает свое действие при снятии с паузы (что, конечно, замечательно, но мне не понятно как это происходит) :wacko:

Код:
Global $Paused = 0
HotKeySet('{PAUSE}', 'TogglePause')
HotKeySet('^q', 'Terminate')

While 1
    Sleep(100)
WEnd

Func TogglePause()
	$Paused = NOT $Paused
	While $Paused
		Sleep(300000)
		If $Paused Then
			;мои действия
		EndIf
	WEnd
EndFunc

Func Terminate()
    Exit
EndFunc
 

agikon

Знающий
Сообщения
789
Репутация
17
всё дело в
Код:
$Paused  = NOT  $Paused

цикл полностью прокручивается если $Paused, и не прокручивается если NOT $Paused
 
Автор
M

Medved

Новичок
Сообщения
27
Репутация
0
Это понятно. Вопрос в другом, когда цикл запущен, обработчик 5 минут спит. В это время пользователь нажимает на кнопку и запускается второй экземпляр обработчика, который меняет глобальную $Paused. В какой момент спящий обработчик узнает об этом изменении? Почему, если за время сна $Paused дважды поменяет свое состояние и вернется к исходному, спящий обработчик все равно остановится?
 

agikon

Знающий
Сообщения
789
Репутация
17
потому что вы нажимаете кнопку {PAUSE} которая запускает функцию TogglePause каждый раз сначала.
 
Автор
M

Medved

Новичок
Сообщения
27
Репутация
0
Но старая при этом остается работать. Ее никто не убивает.


Добавлено:
Сообщение автоматически объединено:

Иными словами, мне нужно, чтоб когда $Paused = 0, действия во всех уже запущенных обработчиках не выполнялись и они завершали работу. Мне в каждой строчке лепить эту проверку или через одну? :D Хочется разобраться в логике обработки таких ситуаций.
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
То есть тебе нужно запускать несколько копий процесса, которые одинаково реагируют на один семафор?
Код:
HotKeySet('^q', 'i_vse')
AdlibRegister("po_50")

While 1
    Sleep(100)
WEnd

Func po_50()
    $STATE=DllCall('user32.dll','int','GetKeyState','int',0x14)
    While BitAND($STATE[0],1) 
        Sleep(300000)
        $STATE=DllCall('user32.dll','int','GetKeyState','int',0x14)
        If BitAND($STATE[0],1) Then
            ;мои действия
        EndIf
        $STATE=DllCall('user32.dll','int','GetKeyState','int',0x14)
    WEnd
EndFunc

Func i_vse()
    Exit
EndFunc

режим паузы - включенный CAPSLOCK
;D
 
Автор
M

Medved

Новичок
Сообщения
27
Репутация
0
C2H5OH
нет, у меня скрипт вроде работает как надо, но возник вопрос почему он работает)
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
HotKey действует как прерывание. То есть повторное нажатие HotKey полностью приостанавливает первый вызов, пока не завершит выполнение повторно вызванная функция, а потом продолжает выполнение первого вызова.
Код:
#Include <Misc.au3>
$file = FileOpen("log.txt", 1)

Global $Paused = 0
Global $n = 0
Dim $otstup[10] = [" ","  ","   ","    ","     ","      ","       ","        ","         ","          "]
HotKeySet('{PAUSE}', 'TogglePause')
HotKeySet('^q', 'Terminate')

While 1
    Sleep(1000)
WEnd

FileClose($file)

Func TogglePause()

	$n += 1
	Local $i = $n
    $Paused = NOT $Paused
	FileWriteLine($file, $otstup[$i] & "процесс " & $i & "  точка 1. Paused = " & $Paused)
    While $Paused
		FileWriteLine($file, $otstup[$i] & "процесс " & $i & "  точка 2. Paused = " & $Paused)
        Sleep(10000)
		FileWriteLine($file, $otstup[$i] & "процесс " & $i & "  точка 3. Paused = " & $Paused)
        If $Paused Then
            ;мои действия
			FileWriteLine($file, $otstup[$i] & "процесс " & $i & "  точка 4. Paused = " & $Paused)
        EndIf
    WEnd
	FileWriteLine($file, $otstup[$i] & "процесс " & $i & "  точка 5. Paused = " & $Paused)
EndFunc

Func Terminate()
    Exit
EndFunc


[box title=log] процесс 1 точка 1. Paused = True
процесс 1 точка 2. Paused = True
процесс 1 точка 3. Paused = True
процесс 1 точка 4. Paused = True
процесс 1 точка 2. Paused = True
процесс 1 точка 3. Paused = True
процесс 1 точка 4. Paused = True
процесс 1 точка 2. Paused = True
процесс 1 точка 3. Paused = True
процесс 1 точка 4. Paused = True
процесс 1 точка 2. Paused = True
процесс 2 точка 1. Paused = False
процесс 2 точка 5. Paused = False
процесс 3 точка 1. Paused = True
процесс 3 точка 2. Paused = True
процесс 3 точка 3. Paused = True
процесс 3 точка 4. Paused = True
процесс 3 точка 2. Paused = True
процесс 3 точка 3. Paused = True
процесс 3 точка 4. Paused = True
процесс 3 точка 2. Paused = True
процесс 3 точка 3. Paused = True
процесс 3 точка 4. Paused = True
процесс 3 точка 2. Paused = True
процесс 4 точка 1. Paused = False
процесс 4 точка 5. Paused = False
процесс 3 точка 3. Paused = False
процесс 3 точка 5. Paused = False
процесс 1 точка 3. Paused = False
процесс 1 точка 5. Paused = False[/box]
 
Автор
M

Medved

Новичок
Сообщения
27
Репутация
0
C2H5OH
С файлом проследить я и не догадался. Спасибо, надо обдумать.


Добавлено:
Сообщение автоматически объединено:

Можно ли как-то запретить прерывать блок "мои действия"? Они должны отработать достаточно быстро, но вдруг по воле случая прерывание придет во время их исполнения :scratch:
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Не совсем понятна логика запрета.
Суть HotKey - всё остановить и выполнить меня.
Можно написать
Код:
Global $semafore = 0
...
Func TogglePause()
    If $semafore Then Return
    $Paused = NOT $Paused
    While $Paused
        Sleep(10000)
       If $Paused Then
            $semafore = 1
            ;мои действия
            $semafore = 0
        EndIf
    WEnd
EndFunc


Но это будет означать что если во время выполнения "моих действий" была нажата HotKey, то вызов функции по ней просто ничего не сделает. Хотя можно сначала поменять $Paused, а потом проверить семафор.
Код:
Func TogglePause()
    $Paused = NOT $Paused
    If $semafore Then Return
    ...
 
Автор
M

Medved

Новичок
Сообщения
27
Репутация
0
Логика запрета в том, что обработчик должен выполнить некоторые полезные "мои действия" целиком если начал, либо не выполнить их вовсе, если пришла отмена до того как. Как транзакция в БД. "Мои действия", разорванные во времени, теряют полезность :smile: Кроме того, при отмене паузы тоже выполняются ряд операций, которые полагаются на детерминированное состояние объекта управления, а не неопределенное, которое случится в случае прерывания блока "мои действия". Как-то так.

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

Еще такой вопрос. Время сна в основном бесконечном цикле на что-то влияет?
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Время сна в основном бесконечном цикле на что-то влияет?
Нет, не влияет. HotKey сработает одинаково независимо от операций и пауз в основном цикле.
 
Автор
M

Medved

Новичок
Сообщения
27
Репутация
0
Вопросов больше не имею. Спасибо :beer:
 
Верх