很多人第一次听到 AHK_H 的“多线程”会误会:是不是普通 AHK v1 里的热键、定时器也是多线程?严格说不是。普通 v1 的热键、菜单、定时器更像同一个解释器里的任务切换;而 AHK_H 的 AhkThread() 可以在当前进程里创建额外的 AutoHotkey 线程,底层依赖 AutoHotkey.dll。

所以,AHK_H 能多线程的核心不是某个语法糖,而是它能在同一个进程里再开一个 AutoHotkey 解释器环境。每个线程有自己的脚本、变量、自动执行段、定时器和消息循环;主线程和子线程之间再通过函数调用、参数、共享对象等方式配合。

最小例子

#Requires AutoHotkey v1.1
#NoEnv
SetBatchLines, -1

threadCode =
(
#Persistent
MsgBox, 这是子线程里的 MsgBox
)

t := AhkThread(threadCode)
MsgBox, 这是主线程里的 MsgBox

ahkthread_free(t)
t := ""

这个例子里,AhkThread(threadCode) 会把一段脚本文本交给新线程执行。主线程拿到的是一个线程对象,后面可以用它调用 H 版 DLL 暴露出来的方法。

线程不是 Include

  • #Include 是把代码合并进当前脚本,仍然是一个解释器环境。
  • AhkThread() 是启动另一个 AHK 线程,它有自己的全局变量和自动执行段。
  • 子线程里需要长期等待函数调用、定时器或热键时,通常要写 #Persistent
  • 主线程退出时,子线程一般也会跟着结束;正式脚本应主动释放线程对象。

传参数用 A_Args

AhkThread() 的第二个参数可以传给子线程,在线程内部通过 A_Args 读取。这适合传简单配置、任务名、路径等字符串。

threadCode =
(
#Persistent
MsgBox, % "收到参数:" A_Args[1]
)

t := AhkThread(threadCode, "task-001")

调用线程里的函数

实际开发里,不一定让线程启动后马上做完所有事情。更常见的是先启动线程,再用 ahkFunction()ahkPostFunction() 调用线程里的函数。

threadCode =
(
#Persistent
Work(name) {
    Sleep, 1000
    return "完成任务:" name
}
)

t := AhkThread(threadCode)

; 同步调用:等待返回值
MsgBox, % t.ahkFunction("Work", "A")

; 异步调用:投递任务后马上返回
ret := t.ahkPostFunction("Work", "B")
MsgBox, % "投递结果:" ret

什么时候值得用多线程

  • 耗时计算、批量处理、压缩解压、网络等待,可以考虑拆到子线程。
  • GUI 主线程需要保持响应时,可以把慢任务交给子线程。
  • 只是几个热键、几个窗口操作,不建议为了“高级”强行多线程。
  • 多个线程共享对象时要用 CriticalObject() 等机制,并尽量减少高频锁竞争。

入门结论

AHK_H 的多线程能力来自 AutoHotkey.dll。AhkThread() 是最适合新手使用的入口,它把底层的 DLL 调用包装成对象写法。先理解“每个线程都是一份独立脚本环境”,再去研究对象共享、消息通信、函数调用,思路会清楚很多。更多函数可以从 AHK_H 帮助文档 继续查。

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。