AutoHotkey 的单线程特性
- 默认行为:AutoHotkey 是一个脚本语言,默认是单线程运行。这意味着:
- 脚本中的每一行代码会按照顺序执行,后面的代码需要等前面的执行完成。
- 如果某个代码片段运行时间很长,整个脚本会暂停,直到该代码执行完成。
单线程的局限性
- 多任务效率不够:在处理多个任务时,单线程需要逐个完成任务,不能同时进行。
- 响应延迟阻塞:如果脚本中某些任务(如文件操作、网络请求)耗时较长,会导致其他任务暂停。
多线程与单线程的区别:
- 单线程顺序执行:ABCDEFG,HIJKLMN
- 单线程异步执行:ABC,KLMN,EFGHI,错开执行避免I/O之类的长时间等待卡住线程【WinWait】
- 多线程:一个进程内可有多个线程ABCDEFG同时执行互不干扰
- 多进程:创建多个进程ABCDEFG并互相通信,来达到仿多线程的效果。
为什么要用多进程模拟多线程?
由于 AutoHotkey 默认是单线程的,我们可以通过多进程的方式来实现类似“多线程”的效果。这意味着:
- 每个“任务”用一个独立的 AutoHotkey 进程运行。
- 主脚本负责管理和协调这些子进程。
多进程的优势
- 提高效率:多个进程可以并行运行,不会相互阻塞。
- 任务隔离:即使某个进程出现错误,也不会影响主脚本和其他进程的运行。
因为AHK没有多进程模型和管理功能,缺少对进程之间的 数据交换、资源共享、同步机制(如锁、事件、条件变量等)等功能,所以AHK更加适合开多进程做不同的任务。
另一个可以通信的多进程实现:AHK进程通信的模板示例
代码示例:
; 【多进程代替多线程函数】 Exec() By FeiYue 修改优化:dbgba
;
; 使用说明:
; 1、启动进程:Exec(代码,进程标记)
; 2、停止进程:Exec("",进程标记)
; 3、进程标记相同,后启动的进程会替换先启动的进程
; 4、主脚本退出时,主脚本启动的所有进程都会被清理
; 如果是编译后运行,需要电脑安装ahk和此脚本提权到管理员
;-- 这是一行的写法
F1::Exec("Loop{`nSleep,100`nMouseGetPos,x,y`nToolTip,F1-%A_Index%,x+10,y-30`n}", 1)
;-- 这是多行的写法,括号中可以原样粘贴要运行的代码
F2::
s=
(` %
Loop {
Sleep, 100
MouseGetPos, x, y
ToolTip, F2-%A_Index%, x+10, y+10
}
)
;-- 使用开关变量来一键切换启动和停止
; (ok:=!ok) ? Exec(s,2) : Exec("",2)
Exec(s, 2)
return
;-- 清理进程
F3::Exec("", 1), Exec("", 2)
Exec(s, flag="Default", Timeout=30) {
Static PIDLabel := DllCall("GetCurrentProcessId")
SetBatchLines -1
SetWorkingDir %A_ScriptDir%
add=`nflag=<<ExecNew%PIDLabel%%flag%>>`n
(%
Gui, Gui_Flag_Gui: Show, Hide, %flag%
与进程同步退出(PID:="") {
Static init:=与进程同步退出(_HostProcessID)
if (PID="")
ExitApp
else
DllCall("RegisterWaitForSingleObject", "Ptr*", 0, "Ptr", DllCall("OpenProcess", "Uint", 0x100000, "int", False, "Uint", PID, "Ptr"), "Ptr", RegisterCallback("与进程同步退出", "F"), "Ptr", 0, "Uint", -1, "Uint", 8)
}
)
DetectHiddenWindows % ("On", DHW:=A_DetectHiddenWindows)
WinGet, NewPID, PID, <<ExecNew%PIDLabel%%flag%>> ahk_class AutoHotkeyGUI
SendMessage, 0x111, 65307,,, %A_ScriptDir%\* ahk_pid %NewPID%
exec := ComObjCreate("WScript.Shell").Exec(A_AhkPath " /ErrorStdOut /force *")
, exec.StdIn.Write(StrReplace(add, "_HostProcessID", PIDLabel) "`n" s "`nExitApp")
, exec.StdIn.Close()
if (s!="")
Loop % Timeout*1000//15
Sleep 15
Until WinExist("<<ExecNew" PIDLabel . flag ">> ahk_pid " exec.ProcessID)
DetectHiddenWindows %DHW%
Return exec.ProcessID
}
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。

评论(0)