autohotkey的异步执行如何工作?

时间:2016-07-08 13:29:18

标签: asynchronous autohotkey

这是我发现的示例程序,它允许您切换一些循环操作:

SetTimer

现在我们可以看到有一些超时类型的调用会启动无限循环。无限循环显然是同步的,没有回调或同步块或任何东西。

仍然,按 F12 似乎可以正常停止循环,即使它正在运行。

有人可以向我解释如何在autohotkey中执行线程吗?如何在没有竞争条件的情况下处理多个代码块? {{1}}调用是否在此中扮演任何角色?

2 个答案:

答案 0 :(得分:5)

TLDR:线程可以互相中断。

查看AHK docs on Threads

  

虽然AutoHotkey实际上并不使用多个线程,但它   模拟一些行为:如果第二个线程启动 - 这样   通过在前一个仍在运行时按另一个热键 -   当前线程将被中断(暂时停止)以允许   新线程成为当前的。如果第三个线程启动的话   第二个仍在运行,第二个和第一个将在一个   休眠状态,等等。

新线程与当前线程

因此,在您的示例中,如果按下F12togglefalse,则会立即运行loop子例程且仅运行一次-1期)。子程序将循环,直到toggle再次成为false 诀窍就是:如果再次按F12,则运行另一个线程,新线程默认中断当前线程。所以新线程将暂停循环,将toggle设置为false然后优雅地完成,因为热键子例程没有任何事情要做。热键子例程完成后,前一个线程(我们的loop计时器)恢复生机。由于toggle现在是false,它会突破循环并完成...所以圈子就完成了。请注意loop被命令只运行一次,所以不再重复。

线程优先级

如果priorityAHK docs on Sleep至少等于当前线程的优先级,则新线程只能中断当前线程。默认情况下,每个线程的优先级都为0,如果它是热键线程,定时子例程或任何其他类型的线程,则无关紧要。当然,有一个例外...

使用Sleep

dropbox gem说:

  

在睡觉时,可以通过热键自定义菜单启动新线程   项目或计时器。

如果线程处于休眠状态,它基本上会被中断,并为任何其他线程释放所有 CPU时间(仅在它实际休眠的时间)。也就是说,即使具有较低优先级的线程也可以在当前线程休眠时运行。在您的示例中,有大约Sleep 700毫秒。当然,即使没有睡眠,您的脚本也可以正常工作,toggle仍然可以切换。但是即使loop被调用的优先级更高,在loop正在睡觉时(实际上大部分时间都是如此),仍然能够运行。

示例代码发臭

您发布的代码示例可能有效,但IMO,令人困惑且完全不好编码。定时器的主要目的是定期运行,但这里我们在定时器中有一个循环,它违背了定时器的整个目的。 如果我们允许Hotkey产生多个线程,我们甚至可以使用这个荒谬但有效的代码:

; Bad example!
#MaxThreadsPerHotkey 2
toggle := false

F12::
    toggle := !toggle
    while(toggle) {
        SoundBeep
        Sleep, 500 ; Would even work without the Sleep
    }
return

使用计时器来实现它们的目的

以下是我将如何实现每700毫秒点击一次的切换功能:

toggle := false

F12::
    toggle := !toggle
    if(toggle) {
        SetTimer, DoLeftClick, Off
    } else {
        SetTimer, DoLeftClick, 700
    }
return

DoLeftClick:
    Click
return

答案 1 :(得分:2)

不要认为这是一个完整的答案 我想补充一点,因为v1.1.20你应该几乎总是使用函数而不是标签。这避免了许多潜在的冲突(标签在全球范围内执行) 所以你最好这样做:

F12::
__F12() {
    Static toggle := False
    toggle := !toggle
    SetTimer, DoLeftClick, % toggle ? 700 : "Off"
}

DoLeftClick() {
    Click
}