如何使用内部循环等待函数完成

How to await function completion with a loop inside

在下面包含的脚本中,我尝试 运行 一系列命令。但是当 运行 按 F1 时,该命令将 运行 两个 SendAndLoopFor() 调用紧接着彼此调用,而不等待内部循环完成。

我试图通过在函数内添加一个 return "" 来 'force' 等待,并用它分配一个变量 Foo := SendAndLoopFor() 但即便如此它也不会等待操作.

有没有办法在执行下一个命令之前等待 SendAndLoopFor() 命令完成?

#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%  
#MaxThreadsPerHotkey 13
#SingleInstance
F1::
Done = 0
Toggle := !Toggle
Loop
{
    If (!Toggle)
        Break
    SendAndLoopFor("4", -13600)
    SendAndLoopFor("5", -13600)
}
return

SendAndLoopFor(TSend="", Timeout=0)
{
    Send %TSend%
    SetTimer, LoopLimit, %Timeout%
    Loop
    {
        If(!Toggle)
            Break
        If(done == 1)
        {
            done = 0
            Break
        }
        MouseClick, left
        sleep 83
    }
}
LoopLimit:
    Done = 1
Return

你的问题好像是对SetTimer的误解。它是并行化任务的绝佳工具,因为脚本本身不会在继续执行脚本之前等待计时器。

为了说明这一点,简化脚本,您可以观察到相同的效果。

F3::
SetTimer, LoopLimit, -2000
SendInput, This is stuff happening before the timer.{Enter}
return

LoopLimit:
SendInput, This is stuff happening after.

一个简单的解决方案是计算迭代次数并在达到计数器限制后终止循环。

F3::
count = 0

Loop
{
; Do stuff.

count += 1
Sleep, 1000

if (count >= 5)
{
break
}}

您还可以使用 various built-in variables 来比较从循环开始到您的截止值的时间,但是使用这些可能会很痛苦,所以我建议避免使用它们,除非您的脚本在其中运行时间敏感的约束。

根据评论编辑:

F1::
Done = 0
Toggle := !Toggle
Loop
{
    If (!Toggle)
        Break
    SendAndLoopFor("4", -13600)
    SendAndLoopFor("5", -13600)
    Sleep, 2000
}
return

SendAndLoopFor(TSend="", Timeout=0)
{
    Send %TSend%
    SetTimer, LoopLimit, %Timeout%
    Loop
    {
        If(!Toggle)
        {
            SendInput, This is inside the Toggle.{Enter}
            Break
        }
        If(done == 1)
        {
            SendInput, This is inside the Done.{Enter}
            done = 0
            Break
        }
        SendInput, This is after the If statements.{Enter}
        MouseClick, left
        Sleep, 999999 ; Note how this has no effect due to above break.
    }
}
LoopLimit:
    Done = 1