</head> <body> <h1>线程</h1> <p><em>当前线程</em> 的定义为最近事件调用的执行流; 例如包括<a href="../Hotkeys.htm">热键</a>, <a href="../lib/SetTimer.htm">计时器子程序</a>, <a href="../lib/Menu.htm">自定义菜单项</a>和 <a href="../lib/Gui.htm#Events">GUI 事件</a>. <em>当前线程</em> 可以在其自身子程序或该子程序调用的其他子程序中执行函数.</p> <p>尽管 AutoHotkey 实际上并不支持多线程, 但它模拟了多线程的某些特性: 如果启动了第二个线程 -- 例如在前一个线程仍在执行时按下另一个热键 -- 那么 <em>当前线程</em> 会被中断(暂时停止) 以允许新线程变为 <em>当前线程</em>. 如果在第二个线程还在运行时又启动了第三个线程, 那么第二个和第一个线程都会进入休眠状态, 依此类推.</p> <p>当 <em>当前线程</em> 结束时, 将恢复执行最近中断的线程, 依此类推, 直到所有线程最终结束. 当线程被恢复时, 它的设置例如 <a href="../lib/SendMode.htm">SendMode</a> 和 <a href="../lib/SetKeyDelay.htm">SetKeyDelay</a> 会自动恢复到中断前的状态; 换句话说, 中断不会给线程带来副作用(<a href="../lib/WinActivate.htm">活动窗口</a>可能发生的更改除外).</p> <p class="note"><strong>注意:</strong> <a href="../lib/KeyHistory.htm">KeyHistory</a> 函数/菜单项会显示处于中断状态的线程数量, 而 <a href="../lib/ListHotkeys.htm">ListHotkeys</a> 函数/菜单项则显示拥有线程的热键.</p> <p>一个脚本可以有多个同时发生的 <a href="../lib/MsgBox.htm">MsgBox</a>, <a href="../lib/InputBox.htm">InputBox</a>, <a href="../lib/FileSelect.htm">FileSelect</a> 和 <a href="../lib/DirSelect.htm">DirSelect</a> 对话框. 这是在前一个线程已经显示对话框时, 通过启动一个新的线程(通过<a href="../Hotkeys.htm">热键</a>, <a href="../lib/SetTimer.htm">计时器子程序</a>, <a href="../lib/Menu.htm">自定义菜单项</a>, 等.) 来实现的.</p> <p>默认情况下, 如果给定的<a href="../Hotkeys.htm">热键</a>或<a href="../Hotstrings.htm">热字串</a>子程序已经在运行, 则不能再次启动. 请使用 <a href="../lib/_MaxThreadsPerHotkey.htm">#MaxThreadsPerHotkey</a> 来改变此特性.</p> <p><strong>相关:</strong> <a href="../lib/Thread.htm">Thread</a> 函数用于设置线程的优先级或中断性.</p> <h2 id="Priority">线程优先级</h2> <p>任何优先级低于 <em>当前线程</em> 的线程(<a href="../Hotkeys.htm">热键</a>, <a href="../lib/SetTimer.htm">计时子程序</a>, <a href="../lib/Menu.htm">自定义菜单项</a>, 等.), 不能中断当前线程. 在这种时候, 如计时器不会运行, 任何用户创建线程(如, 通过按下<a href="../Hotkeys.htm">热键</a>或 <a href="../lib/GuiControls.htm#Button">GUI 按钮</a>) 的尝试都不会产生任何效果, 也不会被缓存起来. 由于这个原因, 通常在设计时最好让高优先级的线程快速结束, 或使用 <a href="../lib/Critical.htm">Critical</a> 而不将它们设置成高优先级.</p> <p>默认的优先级为 0. 所有线程使用默认的优先级, 不过可以使用下列的其中一种方法来改变:</p> <ul> <li>通过 <a href="../lib/SetTimer.htm">SetTimer</a> 给计时子程序指定优先级.</li> <li>通过 <a href="../lib/Hotkey.htm">Hotkey</a> 函数给热键指定优先级.</li> <li>在定义<a href="../Hotstrings.htm">热字串</a>时指定优先级, 或通过 <a href="../lib/_Hotstring.htm">#Hotstring</a> 指令给热字串指定优先级.</li> <li>通过 <a href="../lib/Menu.htm#Add">Menu.Add</a> 方法给自定义菜单项指定优先级.</li> <li>通过 <a href="../lib/Thread.htm">Thread</a> 函数给 <em>当前线程</em> 设置自己的优先级.</li> </ul> <p>不论 <em>当前线程</em> 的优先级如何, <a href="../lib/OnExit.htm">OnExit</a> 回调函数(如果有) 被调用时总是会运行.</p> <h2 id="Interrupt">线程可中断性</h2> <p>对于大多数类型的事件, 只有在当前线程 <em>可中断</em> 的情况下, 才允许启动新的线程. 一个线程可以因为一些原因而 <em>不可中断</em>, 包括:</p> <ul> <li>线程已被标记为 <em>critical</em>. <a href="../lib/Critical.htm">Critical</a> 可能已经被线程本身或被<a href="../Scripts.htm#auto">自动执行线程</a>调用.</li> <li>线程运行时间不够长, 无法满足线程中断设置的成为可中断的条件, 如 <a href="../lib/Thread.htm#Interrupt">Thread Interrupt</a> 设置的.</li> <li>脚本的一个菜单正在显示(如<a href="Program.htm#tray-icon">托盘图标</a>菜单或菜单栏).</li> <li><a href="../lib/Send.htm">Send</a>(最常见的是由于 <a href="../lib/SetKeyDelay.htm">SetKeyDelay</a>), <a href="../lib/WinActivate.htm">WinActivate</a> 或 <a href="../lib/../lib/A_MenuMaskKey.htm">Clipboard</a> 操作正在执行延迟.</li> <li><a href="../lib/OnExit.htm">OnExit</a> 线程正在执行.</li> <li>由于达到了 <a href="../lib/A_MaxHotkeysPerInterval.htm">A_MaxHotkeysPerInterval</a> 的限制, 或者由于激活键盘或鼠标钩子的问题(非常罕见), 正在显示一个警告对话框.</li> </ul> <h3 id="Behave">不可中断线程的特性</h3> <p>与高优先级线程不同, 线程不可中断时产生的事件不会被丢弃. 例如, 在当前线程不可中断时用户按下了<a href="../Hotkeys.htm">热键</a>热键就会被无限期地缓冲, 直到当前线程结束或变得可中断时, 热键才作为新的线程启动.</p> <p>在紧急情况下, 任何线程都可能被中断. 紧急情况包括:</p> <ul> <li>一个 <a href="../lib/OnExit.htm">OnExit</a> 回调.</li> <li>任何监视没有<a href="../lib/OnMessage.htm#buffering">缓冲</a>的消息的 <a href="../lib/OnMessage.htm">OnMessage</a> 函数.</li> <li>任何由线程自身间接触发的<a href="../lib/CallbackCreate.htm">回调</a>(例如, 通过 <a href="../lib/PostMessage.htm">SendMessage</a> 或 <a href="../lib/DllCall.htm">DllCall</a>).</li> </ul> <p>要避免被这些事件中断, 可以临时禁用这些函数.</p> <p>当显示 <a href="../lib/MsgBox.htm">MsgBox</a> 或其他对话框时, <a href="../lib/Critical.htm">critical</a> 会变得可中断. 但与 <a href="../lib/Thread.htm#Interrupt">Thread Interrupt</a> 不同的是, 在用户解除对话框后, 线程又变成了 critical(因此不可中断).</p> </body> </html>