Critical

防止当前线程被其他线程中断。

Critical [, Off]
Critical 50 ; 请参阅备注底部

如果首个参数省略 (或为单词 On), 则设置 当前线程 为关键的, 这意味着它不会被其他线程中断. 如果首个参数为 Off(或在 v1.0.48+ 为数字 0),则当前线程会不论 Thread Interrupt 设置如何都会变成可中断状态。

高优先级 线程不同, 在关键线程中产生的事件不会被丢弃. 例如, 在当前线程为关键线程时用户按下了 热键, 那么此热键会被缓冲到当前线程结束或成为非关键线程时才作为新的线程启动.

关键线程也会被紧急事件中断. 紧急事件包括: 1) OnExit 子程序; 2) 监听消息号小于 0x312 的任何 OnMessage() 函数 (或被这些消息触发的 回调); 和 3) 由紧急线程自身间接触发的任何 回调 (例如通过 SendMessageDllCall). 要避免被这些事件中断, 可以临时禁用这些函数.

当被缓冲的事件等待启动新线程时, 使用 "Critical Off" 不会立即中断当前线程. 相反, 需要经过平均 5 毫秒的时间才会进行中断. 这样在中断前, 有 99.999% 的可能性至少执行了 "Critical Off" 后的一行代码. 您可以通过延迟(例如 Sleep -1 或使用 WinWait 等待不存在的窗口),这样可以强制立即产生中断。

关键线程在显示 MsgBox 或其他对话框时, 会变成可中断的. 但是,与 Thread Interrupt 不同,在用户解除对话框后这个线程会再恢复为关键的。

请参阅 A_IsCritical 了解如何保存和恢复 Critical 的当前设置. 然而,由于Critical是特定于线程的设置,所以当关键线程结束后,在它后面的/待恢复的线程(如果有)会自动成为非关键的。因此, 不需要在关键线程结束前执行 "Critical Off".

如果在自动执行段(脚本的顶部)没有使用 Critical,那么所有线程初始都为非关键的(然而还是会应用 Thread Interrupt 的设置)。与之相比, 如果在自动执行段中打开了 Critical 且从没有关闭过, 那么每个新启动的 线程 (例如 热键, 自定义菜单项计时 子程序) 初始都为关键的.

Thread NoTimers 命令类似于 Critical,不过它只防止被计时器中断。

在 v1.0.47+,打开 Critical 的同时也会让 SetBatchLines -1当前线程生效。

在 v1.0.47+,在首个参数中使用正数(例如 Critical 30)会打开 Critical,但同时也改变了检查内部消息队列的间隔时间。如果没有指定数字, 则当 Critical 设置为 On 时会每隔 16 毫秒检查消息, 而 Critical 为 Off 时会每隔 5 ms 检查消息. 增加这个间隔可以延迟消息/事件的达到, 这样给 当前线程 更多的时间来结束. 这样降低了由于 "线程已经运行" 而丢失某些 OnMessage()GUI 事件 的可能性. 然而,等待的命令(例如 SleepWinWait)会不论此设置如何都使用默认间隔检查消息(一种解决方法是 DllCall("Sleep", Uint, 500))。注意: 增加消息检查间隔太多可能会降低各种事件的实时响应性, 例如 GUI 窗口重绘.

相关

Thread(命令), 线程, #MaxThreadsPerHotkey, #MaxThreadsBuffer, OnMessage(), RegisterCallback(), Hotkey, Menu, SetTimer

示例

#space::  ; Win+Space 热键.
Critical
ToolTip No new threads will launch until after this ToolTip disappears.
Sleep 3000
ToolTip  ; 关闭提示.
return  ; 从热键子程序中返回, 这样结束了当前线程. 后面的线程会按设置恢复为非关键的.