Tom*_*ica 3 asynchronous autohotkey
这是我发现的示例程序,它将允许您切换一些循环操作:
; This toggles the action
toggle:=false
F12::
; If true is assigned to toggle, loop starts
; It also can assign false even when loop is running
If (toggle := !toggle)
SetTimer, loop, -1
return
loop:
; Endless loop? Actually not, the value of toggle can be changed by
; another "thread" even when this loop is running
while toggle
{
Click
Sleep, 700
}
return
Run Code Online (Sandbox Code Playgroud)
现在我们可以看到有一些超时调用开始了无限循环。无限循环显然是同步的,没有回调或同步的块或任何东西。
尽管如此,按F12一下似乎可以正确停止循环,即使循环正在运行也是如此。
有人可以向我解释如何在autohotkey中执行线程吗?如何在没有竞争条件的情况下处理多个代码块?是否SetTimer调用在其中发挥什么作用?
TLDR:线程可以互相中断。
尽管AutoHotkey实际上并没有使用多个线程,但是它模拟了某些行为:如果启动了第二个线程-例如在前一个线程仍在运行时通过按下另一个热键-当前线程将被中断(暂时中止)到允许新线程成为当前线程。如果在第二个线程仍在运行时启动了第三个线程,则第二个线程和第一个线程都将处于休眠状态,依此类推。
因此,在您的示例中,如果F12按和toggle是false,它将立即且仅运行一次loop子例程(周期为)。子例程将循环直到再次变为。
诀窍出在这里:如果再次按,将运行另一个线程,默认情况下,新线程会中断当前线程。因此,新线程将暂停循环,设置为,然后正常结束,因为热键子例程无事可做。热键子例程完成后,上一个线程(这是我们的计时器)恢复工作。从现在开始,它将跳出循环并结束...,因此圈是完整的。请注意-1togglefalseF12togglefalselooptogglefalseloop 被命令只运行一次,所以在那里不再重复。
如果新线程的优先级至少等于当前线程的优先级,则它们只能中断当前线程。默认情况下,每个线程的优先级都为0,并且它是热键线程,定时子例程还是任何其他类型的线程都没有关系。当然,有一个例外...
Sleep在对睡眠AHK文档说:
在睡眠期间,可以通过热键,自定义菜单项或计时器启动新线程。
如果一个线程正在休眠,则它基本上会被中断并为其他任何线程释放所有CPU时间(仅用于其实际休眠的时间)。也就是说,即使优先级较低的线程也可以在当前线程处于休眠状态时运行。在您的示例中,大约Sleep有700毫秒。当然,即使没有睡眠,您的脚本也可以工作并且toggle仍然可以切换。但是,即使loop被优先级较高地调用,该曲棍球仍可以在loop睡眠时运行(这实际上是大多数时间)。
您发布的代码示例可能有效,但IMO令人困惑,并且完全是错误的代码。计时器的主要目的是定期运行,但是这里我们在计时器中存在一个循环,这违背了计时器的全部用途。如果我们允许热键产生多个线程,我们甚至可以使用以下荒谬但有效的代码段:
; Bad example!
#MaxThreadsPerHotkey 2
toggle := false
F12::
toggle := !toggle
while(toggle) {
SoundBeep
Sleep, 500 ; Would even work without the Sleep
}
return
Run Code Online (Sandbox Code Playgroud)
这是实现每700毫秒单击一次的切换功能的方法:
toggle := false
F12::
toggle := !toggle
if(toggle) {
SetTimer, DoLeftClick, Off
} else {
SetTimer, DoLeftClick, 700
}
return
DoLeftClick:
Click
return
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3051 次 |
| 最近记录: |