多线程与单线程的区别:
单线程顺序执行:ABCDEFG,HIJKLMN
单线程异步执行:ABC,KLMN,EFGHI,错开执行避免I/O之类的长时间等待卡住线程【WinWait】
多线程:一个进程内可有多个线程ABCDEFG同时执行互不干扰
多进程:创建多个进程ABCDEFG并互相通信,来达到仿多线程的效果。
通过调用AHK_V1_H版的方式,实现多线程的函数库。
H版dll只有主进程对子线程的控制,没有子线程对主进程的控制。
想实现子线程对主进程的汇报或控制,可以参考多进程函数库的WM_COPYDATA通信方法
多进程函数库的链接:https://www.autoahk.com/archives/38591
/*
═══════════════════════════════════════════════════════════
AHK_L版调用H版dll实现多线程方法
详见H版帮助文档:https://hotkeyit.github.io/v1/docs/commands/AhkThread.htm
以下为简单演示:
ahk.textdll(代码内容, 线程编号, 可传参) ; 开启一个新线程
ahk.Terminate(线程编号) ; 结束指定线程 【ahk.textdll("", 1)也可结束】
更多比如线程重启、暂停、在线状态,调用线程中的函数,给线程的变量赋值,检查
线程中变量的值,指定线程跳转标签等解释请查看Lib\AhkLThread.ahk
═══════════════════════════════════════════════════════════
*/
#Include <AhkLThread>
; 以下为创建新线程多行写法
s=
(` %
; #NoTrayIcon ; 关闭新线程托盘图标显示
Loop {
Sleep 10
MouseGetPos, x, y
ToolTip % A_Args[1] A_Index, x+10, y-70
}
Return
MyFunc(可传参, 可传参2) {
MsgBox, , 1号线程对话框, % "传参1内容为:" 可传参 "`n传参2内容为:" 可传参2
}
标签1:
MsgBox, , 1号线程对话框, 仅标签跳转演示`n`nF4给线程赋值:%var%
Return
)
ahk.textdll(s, 1, "传参:1号线程持续运算-")
; 以下为创建新线程单行写法
ahk.textdll("Loop {`nSleep 10`nMouseGetPos, x, y`nToolTip % A_Args[1] A_Index, x+10, y-30`n}", 2, "传参:2号线程持续运算-")
; 调用外部脚本文件的写法
; ahk.dll("外部脚本文件名.ahk", 3, "传参运行线程333")
MsgBox, , 主进程对话框, 点击确定后主进程将结束,`n`n连带所有新线程也会跟着结束。
ExitApp
; F1:对1号线程暂停/开启的切换
F1::
if (onoff := !onoff)
ahk.Pause(1)
else
ahk.Pause(1, "Off")
Return
; F2:在1号线程里进行传参并调用函数【归属于1号线程】
F2::ahk.PostFunction(1, "MyFunc", "Hello World!", "第二个参数")
; F3:在1号线程里跳转标签运行【归属于1号线程】
F3::ahk.Label(1, "标签1", 1) ; 仅跳转不赋值
F4::
ahk.Assign(1, "var", "123456") ; 给1号线程的"var"变量赋值
MsgBox, , 主进程对话框, % "给1号线程的 var 变量赋值为:" ahk.Getvar(1, "var") ; 主进程查看1号线程的变量内容
Return
AhkLThread.ahk
; 更多解释详见H版帮助文档:https://hotkeyit.github.io/v1/docs/commands/AhkThread.htm
Class ahk {
; 以脚本文件来新建线程:ahk.dll("外部脚本文件名.ahk", 1)
dll(脚本路径, 线程编号, 传参:="") {
ahk.新建线程文件(线程编号)
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkdll", "Str", 脚本路径, "Str", , "Str", 传参, "Ptr")
Return Rtn
}
; 以脚本内容新建线程:ahk.textdll("MsgBox Hello World!", 1)
textdll(脚本内容, 线程编号, 传参:="") {
ahk.新建线程文件(线程编号)
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahktextdll", "Str", 脚本内容, "Str", , "Str", 传参, "CDecl")
Return Rtn
}
; 调用线程中的函数【SendMessage】:ahk.Function(1, "MyFunc", "Hello World!")
Function(线程编号, FuncName, Arg1:="", Arg2:="", Arg3:="", Arg4:="", Arg5:="", Arg6:="", Arg7:="", Arg8:="", Arg9:="", Arg10:="") {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkFunction","Str",FuncName,"Str",Arg1,"Str",Arg2,"Str",Arg3,"Str",Arg4,"Str",Arg5,"Str",Arg6,"Str",Arg7,"Str",Arg8,"Str",Arg9,"Str",Arg10,"CDecl Str")
Return Rtn
}
; 调用线程中的函数【PostMessage不等待函数返回】:ahk.PostFunction(1, "MyFunc", "Hello World!")
PostFunction(线程编号, FuncName, Arg1:="", Arg2:="", Arg3:="", Arg4:="", Arg5:="", Arg6:="", Arg7:="", Arg8:="", Arg9:="", Arg10:="") {
DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkPostFunction","Str",FuncName,"Str",Arg1,"Str",Arg2,"Str",Arg3,"Str",Arg4,"Str",Arg5,"Str",Arg6,"Str",Arg7,"Str",Arg8,"Str",Arg9,"Str",Arg10,"CDecl Str")
}
; 指定线程跳转标签【1=不等待返回,0=默认等待】ahk.Label(1, "MyLabel", 1)
Label(线程编号, 标签名, 等待:=0) {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkLabel", "Str", 标签名, "UInt", 等待,"CDecl Int")
Return Rtn
}
; 给线程的变量赋值:ahk.Assign(1, "var", "123456")
Assign(线程编号, Var, Value:="") {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkassign", "Str", Var, "Str", Value, "CDecl")
Return Rtn
}
; 检查线程中变量的值:ahk.Getvar(1, "var")
Getvar(线程编号, Var, GetVar:=0) {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkgetvar", "Str", Var, "UInt", GetVar, "CDecl Str")
Return Rtn
}
; 查看线程运行状态:MsgBox % ahk.Ready(1)
Ready(线程编号) {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkReady")
Return Rtn
}
; 暂停指定线程:ahk.Pause(1, "Off")
Pause(线程编号, 开关:="On") {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkPause", "Str", 开关, "Int")
Return Rtn
}
; 重启指定线程:ahk.Reload(1)
Reload(线程编号, TimeOut:=0) {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkReload", "Int", TimeOut, "Int")
Return Rtn
}
; 结束指定线程:ahk.Terminate(1)
Terminate(线程编号, Timeout:=0) {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkTerminate", "Int", Timeout, "Int")
Return Rtn
}
; https://hotkeyit.github.io/v1/docs/commands/ahkExec.htm
Exec(脚本内容, 线程编号) {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkExec", "Str", 脚本内容, "CDecl")
Return Rtn
}
; https://hotkeyit.github.io/v1/docs/commands/addScript.htm
addScript(脚本内容, 线程编号, 等待执行:=1) {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\addScript", "Str", 脚本内容, "Int", 等待执行, "CDecl")
Return Rtn
}
; https://hotkeyit.github.io/v1/docs/commands/addFile.htm
addFile(脚本路径, 线程编号, 等待执行:=1) {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\addFile", "Str", 脚本路径, "Int", 等待执行, "Cdecl")
Return Rtn
}
; https://hotkeyit.github.io/v1/docs/commands/ahkFindFunc.htm
FindFunc(函数名称, 线程编号) {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkFindFunc", "Str", 函数名称, "CDecl PTR")
Return Rtn
}
; https://hotkeyit.github.io/v1/docs/commands/ahkFindLabel.htm
FindLabel(标签名称, 线程编号) {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkFindLabel", "Str", 标签名称, "CDecl PTR")
Return Rtn
}
; https://hotkeyit.github.io/v1/docs/commands/ahkExecuteLine.htm
ExecuteLine(线程指针, 线程编号, 模式:=0, 等待:=0) {
Rtn := DllCall("AutoHotkeyU" this.bit "H" 线程编号 ".dll\ahkExecuteLine", "Ptr", 线程指针, "UInt", 模式, "UInt", 等待, "PTR")
Return Rtn
}
新建线程文件(线程编号) {
FileCreateDir, %A_Temp%\AHKLThread
this.bit := A_PtrSize=4 ? 32 : 64
if !FileExist(A_Temp "\AHKLThread\AutoHotkeyU" this.bit "H" 线程编号 ".dll")
FileCopy, % A_ScriptDir "\Lib\AutoHotkeyU" this.bit "H.dll", % A_Temp "\AHKLThread\AutoHotkeyU" this.bit "H" 线程编号 ".dll"
DllCall("LoadLibrary", "Str", A_Temp "\AHKLThread\AutoHotkeyU" this.bit "H" 线程编号 ".dll")
}
} ; // Class End
以下是带H版dll的打包下载,如有dll更新可自行替换更新
库文件也放进来的好
请求大佬可以说明一下如何任务分派,以及ahk.textdll(代码内容, 线程编号, 可传参)里面代码内容,是否是原来单线程的完整代码?
各个线程怎么共享变量、共享函数
无法共享
怎么更改AutoHotkeyU64H.dll的位置,打包成exe后必须有这个
知道了
请问发布的L版多线程 不能用在FindText吗?不知道怎才能使用
把FindText类库里的local替换成 ; local 也就是注释掉local
FindText 一次性全部都替换成了; local 但是还不能使用
写的那一行FindText没有问题,不知道问题 出在哪里
解决了,请问但是很容易掉,运行几次就会退出,应该怎么解决
感谢大佬
感谢大佬