使用 AHK_H v2,如何让多个线程共享和更新同一个变量?

Using AHK_H v2, how to have multiple threads share and update the same variable?

我迷路了。这不可能吗?

我需要的:

MainScript.ahk:

LastThing := ""

ThreadsArray := []

Loop %thisMany%{
    threads.Push(NewThread("Second script"))
}

---Do Stuff with LastThing---

SecondScript.ahk:

---Get last thing and put it in LastThing---

我有:

MainScript.ahk:

LastThing := ""
SecondScriptSrc := FileRead("SecondScript.ahk", "`n")

dllpath:=A_AhkDir "\AutoHotkey.dll"
DllCall("LoadLibrary","Str",dllpath) 
DllCall(dllpath "\ahktextdll","Str","","Str","","PTR") 
DllCall(dllpath "\ahkassign", "Str", "LastThing", "Str", LastThing, "CDecl")
DllCall(dllpath "\ahkExec","Str",SecondScriptSrc,"CDecl")
    
LastThing := DllCall(dllpath "\ahkgetvar","Str", "LastThing", "UInt", 1, "Cdecl Str")

SecondScript.ahk

dllpath:=A_AhkDir "\AutoHotkey.dll"
DllCall("LoadLibrary","Str",dllpath) 
LastThing := DllCall(dllpath "\ahkgetvar","Str", "LastThing", "UInt", 1, "Cdecl Str")
LastThing := "thing"
DllCall(dllpath "\ahkassign", "Str", "LastThing", "Str", LastThing, "CDecl")

这就是文档使它看起来像我应该如何做的。 消息框显示随机数,看起来很像指针。 我傻吗?

编辑:如果这不可能,那么 ahkassign 和 ahkgetvar 的意义何在?对我来说,ahkgetvar 的文档确实让您看起来可以执行一个线程,然后从该线程检索一个变量。

dllpath:=A_AhkDir "\AutoHotkey.dll"
DllCall("LoadLibrary","Str",dllpath) ; Load the AutoHotkey module.
DllCall(dllpath "\ahktextdll","Str","","Str","","CDecl") ; start a new thread from file.
DllCall(dllpath "\ahkassign","Str","var","Str","value","CDecl") ; assing value to var
MsgBox DllCall(dllpath "\ahkgetvar","Str","var","UInt",0,"CDecl") ; wait for the thread to exit

我真的无法理解你想用你的代码做什么,但我可以回答你问题的标题。

所以先了解一下 AHK_H v2 文档,不要太认真。它真的过时了,你很容易在尝试 运行 示例脚本等时出错。虽然提供的 chm 文件比在线文档好一点。

那么关于你的脚本,DllCalling 似乎不太好,但最好不要使用它。
没必要。

这是一个完整的工作脚本,我将在下面对其进行解释:

MyObj := CriticalObject({"count": 0})

thread2 := AhkThread("
(
    index := 0
    MyObj := CriticalObject(A_Args[1])
    Loop
    {
        MyObj.count++
        index := A_Index
        Sleep(10)
    }
)", &MyObj "")

thread3 := AhkThread("
(
    index := 0
    MyObj := CriticalObject(A_Args[1])
    Loop
    {
        MyObj.count++
        index := A_Index
        Sleep(50)
    }
)", &MyObj "")

Sleep(Random(500, 2000))
MsgBox("Count: " MyObj.count "`nIterations In Thread2: " thread2.ahkgetvar("index", 0) "`nIterations In Thread3: " thread3.ahkgetvar("index", 0))

所以,首先我们创建一个 critical object。这只是一个简单的 object 和一个 属性, count.

然后我们用 ahkThread() 启动一个新线程。我采用的方法是将简单的脚本作为纯文本写入第一个参数。
如果您不熟悉

"
(
text
text
text
")

表示法,这就是所谓的continuation section.
它只是让我们省去用 `ns.
写一长行的麻烦 然后对于第二个参数 (&MyObj ""),它将一个值传递给 A_Args,正如文档所指定的,我传入了我们的关键 object MyObj 的指针(注意用于检索指针的 & 前缀在 AHK v2 中不可用,但在 AHK_H v2 中可用。
我还将指针与空字符串连接起来(基本上将其转换为字符串)。这只是您需要做的事情,以避免它被自动 StrGet'd。

在我们启动的新线程中,我们创建了一个局部变量index,它只是用来计算该线程完成了多少次循环。
然后我们通过引用我们传递给 A_Args.
的指针再次得到我们的关键 object 然后循环只要 运行s 就可以了,并且递增全局计数器 MyObj.count 和本地计数器 index.

ahkThread() 函数的 return 值存储到变量 thread2 中,因此我们稍后使用 documentation 中指定的许多有用方法之一。

然后我们开始另一个线程,只是我们上面所做的复制粘贴。
然后我们休眠 500 到 2000 毫秒之间的随机时间。
然后我们打印一个显示全局计数器和两个本地计数器的消息框。
本地计数器的总和应等于全局计数器的值。

通过在线程 objects(thread2thread3 上使用 .ahkgetvar() 方法从线程中检索本地计数器的值 index ) 我们之前保存过。
0 (false) 在第二个参数上指定,表示 return 是一个值而不是指针。