1 (изменено: kolotilov256, 2020-03-11 22:14:32)

Тема: AHK: Проблемы с SetTimer

Здравствуйте.

Зачем вообще создавались setTimer'ы в AutoHotKey? Чтобы организовать псевдопоток. Чтобы можно было выполнять одно действие, не препятствуя другому. Вещь благородная. Но стоит лишь немножко усложнить тело метки, выполняемой setTimer'ом, как всё резко летит в бездну и псевдопоток умирает...

Для примера сделал простенький код. В нём, если в 27 строке убрать sleep 500 - обе метки будут выполняться хорошо.
Если sleep 500 оставить, то приоритет метки start ни с того ни с сего становится главным, и не даёт выполняться метке met.

#SingleInstance Force
#Persistent
#NoEnv

t1 := "t1.txt"
t2 := "t2.txt"
t3 := "t3.txt"

var := 1
settimer, met, 250
settimer, start, 250
return

start:
while (var < 20)
{
	out(t1, var " < 20. Wait " A_Index)
	sleep 500
}
out(t1, "var is true")
var := false
return

met:
var++
out(t2, var)
sleep 500
return

;

out(file, var = "")
{
	if !var
		Random, var, 1000, 99999999
	FileAppend, % var "`n", % file
}

Результат программы без sleep 500

+ открыть спойлер

https://i.imgur.com/xXdUgWK.png

Результат программы с sleep 500

+ открыть спойлер

https://imgur.com/k0lFO6T.png

2 (изменено: kolotilov256, 2020-03-11 21:08:29)

Re: AHK: Проблемы с SetTimer

Вообще цель была внедрить использование setTimer'ов в более крупный проект, в котором имеются 2 главных события, которые отслеживаются двумя setTimer'ами.
В результате обнаружения одного из главных событий, хотелось бы запустить ещё один setTimer.
Главная цель в этом: чтобы не помешать выполнению работы предыдущих setTimer'ов.

Но я так понимаю, на автохоткее, без костылей и кучи заморочек эта проблема не решается...
Ибо даже банальная задержка в теле метки setTimer'a уже губит все старания.

Даже если каким-то костылём (аля приоритетом или ещё чем-то) пофиксить эту проблему, где взять гарантии, что метка вновь не забагуется при каких-то других обстоятельствах? Никаких гарантий...

3 (изменено: kolotilov256, 2020-03-11 21:26:04)

Re: AHK: Проблемы с SetTimer

Немного изменив тело программы, проблема решается конечно.

+ открыть спойлер
#SingleInstance Force
#Persistent
#NoEnv

t1 := "t1.txt"
t2 := "t2.txt"
t3 := "t3.txt"

var := 1
settimer, met, 250
settimer, start, 250
return

start:
if (var < 20)
{
	out(t1, var " < 20. Wait ")
	sleep 500
}
else
{	
	out(t1, "var is true")
	var := false
}
return

met:
var++
out(t2, var)
sleep 500
return

;

out(file, var = "")
{
	if !var
		Random, var, 1000, 99999999
	FileAppend, % var "`n", % file
}

Но факт остаётся фактом. Почему while тормозит поток? И самое смешное почему это происходит, только если в другой метке есть sleep 500?

4

Re: AHK: Проблемы с SetTimer

Напишите какой-нибудь самый простой пример, в котором SetTimer ведёт себя не так, как Вы ожидали. Сложно въехать в тему.

5

Re: AHK: Проблемы с SetTimer

ypppu, пример кода в первом посте запусти. Он работает не так, как я от него ожидаю.

6

Re: AHK: Проблемы с SetTimer

kolotilov256 пишет:

Почему while

Потому что. Один. Действующий. Цикл.
А смеятся над собой будете, если поймете.

7

Re: AHK: Проблемы с SetTimer

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

8 (изменено: kolotilov256, 2020-03-11 23:38:04)

Re: AHK: Проблемы с SetTimer

stealzy, так почему во время выполнения тела цикла Loop setTimer не может выполнить параллельно действия в метке? Всё в одном потоке произойдёт. Точно также как множество setTimer'ов выполняют сразу несколько действий с разными метками (друг за дружкой, создавая иллюзию многопоточности)

9

Re: AHK: Проблемы с SetTimer

Таймер может, а цикл нет.

10

Re: AHK: Проблемы с SetTimer

stealzy, т.е в метке, которую хотим использовать в таймере, запрещается делать бесконечные (или конечные, но длительные по исполнению) циклы. А ещё подобные подводные камни, о которых никто нигде не рассказывает, существуют у setTimer'ов?)

11 (изменено: kolotilov256, 2020-03-12 00:17:35)

Re: AHK: Проблемы с SetTimer

Ну окей. Не буду использовать циклы Loop, while, for.

Вот ещё пример кода, который не работает как надо. Здесь что не так?

При нажатии F2 поток "lab1" умирает.

+ открыть спойлер
#SingleInstance Force
#Persistent
#NoEnv

SetTimer, lab1, 250
return

f2::
SetTimer, lab2, 250
return

lab1:
msg_box("lab1 1")
sleep 500
msg_box("lab1 2")
sleep 500
msg_box("lab1 3")
sleep 500
msg_box("lab1 4")
sleep 500
msg_box("lab1 5")
return

lab2:
msg_box("lab2 1")
sleep 500
msg_box("lab2 2")
sleep 500
msg_box("lab2 3")
sleep 500
msg_box("lab2 4")
sleep 500
msg_box("lab2 5")
return

msg_box(var)
{
	msgbox,,%var%,, 0.4
}

Хотя ладно, не умирает. Но нестабильно как-то ведёт себя. Может раз 5 проиграться метка lab2, а потом уже lab1.

12

Re: AHK: Проблемы с SetTimer

Подобные темы периодически появляются. Основное, что следует знать - Autohotkey поддерживает только один поток, настоящей многопоточности быть не может. Можно как-нибудь имитировать потоки с помощью таймеров, но они в любом случае не могут работать параллельно. Здесь всё делается последовательно.
Нажатие горячей клавиши приостанавливает текущий поток. Но не прекращает его. Когда гор. клавиша отработает - предыдущий поток продолжит свою работу. Это поведение можно регулировать специальными командами, директивами.

Есть такая статья "Потоки"; оригинал статьи в AutoHotkey.chm: "Threads", по ссылке из статьи "Hotkeys" (Ник переводчика: semechka). Вот её почитайте.

13

Re: AHK: Проблемы с SetTimer

Какой смысл тогда в setTimer, если можно просто сделать один большой цикл на все события, которые тебе нужны? А не разделять эти события на разные метки setTimer'a ?

14

Re: AHK: Проблемы с SetTimer

Например сделать, чтобы подпрограмма запускалась, скажем, каждую минуту. А как при помощи цикла сделать, чтобы запуск был каждую минуту? Ведь команда Loop не знает, как долго будет выполняться тело цикла - секунду или 10 секунд. Это ведь может зависеть от загрузки ЦП и доступности жёсткого диска.

15

Re: AHK: Проблемы с SetTimer

kolotilov256 пишет:

А ещё подобные подводные камни, о которых никто нигде не рассказывает, существуют у setTimer'ов?)

http://www.script-coding.com/AutoHotkey/SetTimer.html

Таймер, возможно, не сможет запускаться с заданной частотой также в следующих случаях:

1. Центральный процессор сильно загружен выполнением других приложений.
2. Исполнение самой подпрограммы таймера занимает больше времени, чем период времени, заданный в этом таймере,..

16

Re: AHK: Проблемы с SetTimer

Foma, ну это и так очевидно. Волнует больше, что он может сам по себе взять и перестать чекать метку. Либо какой-то другой запуск setTimer'a убьёт предыдущий.