對(duì)于多進(jìn)程代替多線程,并且共享變量,我有了新的嘗試。下面是代碼:
;-----------------------------------
; AHK多線程熱鍵(共享對(duì)象) By FeiYue
;
; 使用方法:(熱鍵開(kāi)啟/關(guān)閉多線程)
;
; 線程變量:=new Thread("標(biāo)簽名稱(chēng)") ; 開(kāi)啟一個(gè)新線程
; 線程變量:="" ; 關(guān)閉這個(gè) “線程變量” 對(duì)應(yīng)的的線程
;
; 對(duì)象名:=new GlobalVar("標(biāo)記") ; 相同的標(biāo)記連接到相同的共享對(duì)象
; 對(duì)象名.r1 到 .r5 ; 實(shí)際是用共享對(duì)象的5個(gè)命名屬性來(lái)讀寫(xiě)字符串
;
; 注意:讀寫(xiě)共享對(duì)象的屬性比較慢,所以盡量減少讀寫(xiě)次數(shù)
;-----------------------------------
; Thread 類(lèi)用于啟動(dòng)多進(jìn)程代替多線程
Class Thread {
__New(RunLabelOrFunc)
{
args:= "/Run=" Trim(RunLabelOrFunc)
if (A_IsCompiled)
Run, "%A_ScriptFullPath%" /f "%args%",,, pid
else
Run, "%A_AhkPath%" /f "%A_ScriptFullPath%" "%args%",,, pid
this.pid:=pid
}
__Delete() {
Process, Close, % this.pid
}
ScriptStart() {
static init:=Thread.ScriptStart()
#NoEnv
#NoTrayIcon
if InStr(A_Args[1], "/Run=")
{
Suspend, On ; 放在函數(shù)靜態(tài)變量初始化中避免熱鍵生效
DllCall("SetWindowText", "Ptr",A_ScriptHwnd, "Str","<AHK>")
}
else Menu, Tray, Icon
}
}
; 這里等所有的函數(shù)靜態(tài)變量都完成初始化再正式運(yùn)行
; 注意這幾句代碼必須放在腳本開(kāi)頭的自動(dòng)執(zhí)行段
if InStr(A_Args[1], "/Run=")
{
if IsLabel(k:=SubStr(A_Args[1], 6))
Gosub, %k%
else if IsFunc(k)
%k%()
ExitApp
}
;======================
; GlobalVar 類(lèi)用于多進(jìn)程共享對(duì)象并用命名屬性讀寫(xiě)字符串
; 目前只提供了5個(gè)屬性作為共享屬性,從 對(duì)象.r1 到 對(duì)象.r5
; 可用 對(duì)象.setvar(k,v)、對(duì)象.getvar(k) 增加自定義的共享屬性
class GlobalVar {
__New(flag:="") {
flag:=RegExReplace(flag, "\W+") ; 盡量用英文標(biāo)記
Loop {
Try {
For wnd in ComObjCreate("Shell.Application").Windows {
if (wnd.GetProperty("container_name") = "Ahk_" flag)
this._obj := wnd
}
if (!this._obj) {
this._obj := ComObjGet("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}")
this._obj.PutProperty("container_name", "Ahk_" flag)
}
if (this._obj)
Break
}
Sleep, 10
}
}
Quit() {
this._obj.Quit()
}
;-- 這種加鎖方式比較慢,但也夠用了
Lock() {
Loop {
if (hwnd:=this._obj.GetProperty("Ahk_Lock_ID"))=""
or !DllCall("IsWindow", "Ptr",hwnd)
{
this._obj.PutProperty("Ahk_Lock_ID", A_ScriptHwnd)
Sleep, 20
if (this._obj.GetProperty("Ahk_Lock_ID")=A_ScriptHwnd)
Break
}
Sleep, 20
}
}
LockOff() {
this._obj.PutProperty("Ahk_Lock_ID", "")
}
setvar(k, v) {
this.Lock()
this._obj.PutProperty("Ahk_" k, v)
this.LockOff()
return v
}
getvar(k) {
this.Lock()
v:=this._obj.GetProperty("Ahk_" k)
this.LockOff()
return v
}
;-- 下面設(shè)置5個(gè)命名屬性作為共享屬性
r1 {
Set {
return this.setvar("r1", value)
}
get {
return this.getvar("r1")
}
}
r2 {
Set {
return this.setvar("r2", value)
}
get {
return this.getvar("r2")
}
}
r3 {
Set {
return this.setvar("r3", value)
}
get {
return this.getvar("r3")
}
}
r4 {
Set {
return this.setvar("r4", value)
}
get {
return this.getvar("r4")
}
}
r5 {
Set {
return this.setvar("r5", value)
}
get {
return this.getvar("r5")
}
}
}
;======================
; 顯示控制臺(tái)并輸出內(nèi)容(默認(rèn)自動(dòng)添加換行)
log(ByRef str:="", rn:=1)
{
if !DllCall("GetConsoleWindow")
{
IfWinExist, ahk_class ConsoleWindowClass
WinGet, pid, PID
else
{
Run, cmd.exe /k "echo off",,, pid
WinWait, ahk_pid %pid%
}
DllCall("AttachConsole", "Int",pid)
}
FileAppend, % str (rn ? "`r`n":""), *
}
; 關(guān)閉控制臺(tái)(手動(dòng)關(guān)閉會(huì)退出AHK程序)
logoff()
{
DllCall("FreeConsole")
}
;======== 上面的代碼放在腳本開(kāi)頭自動(dòng)執(zhí)行段 ========
; 使用 多線程 和 共享變量 的例子
;-- 主進(jìn)程設(shè)置共享屬性 .r1 的初始值,并顯示控制臺(tái)
num:=new GlobalVar(), num.r1:=0, log()
*F3:: MsgBox, 4096,, % "當(dāng)前 r1 的值:" num.r1, 1
;-- 【按住松開(kāi)型】熱鍵
*F1::
aaa1:= new Thread("a1")
KeyWait, F1
aaa1:=""
return
;-- 子進(jìn)程1讀寫(xiě)共享屬性 .r1
a1:
if (!num1)
num1:=new GlobalVar()
Loop {
a:=num1.r1, num1.r1:=(a+=2)
log("按住松開(kāi)型循環(huán)-" a)
Sleep, 100
}
return
;-- 【按兩次開(kāi)關(guān)型】熱鍵
*F2::
aaa2:=(onoff:=!onoff) ? new Thread("a2") : ""
return
;-- 子進(jìn)程2讀寫(xiě)共享屬性 .r1
a2:
if (!num2)
num2:=new GlobalVar()
Loop {
b:=num2.r1, num2.r1:=(++b)
log("按兩次開(kāi)關(guān)型循環(huán)-" b)
Sleep, 100
}
return