使用 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.
它只是让我们省去用 `n
s.
写一长行的麻烦
然后对于第二个参数 (&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(thread2
和 thread3
上使用 .ahkgetvar()
方法从线程中检索本地计数器的值 index
) 我们之前保存过。
0
(false) 在第二个参数上指定,表示 return 是一个值而不是指针。
我迷路了。这不可能吗?
我需要的:
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.
它只是让我们省去用 `n
s.
写一长行的麻烦
然后对于第二个参数 (&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(thread2
和 thread3
上使用 .ahkgetvar()
方法从线程中检索本地计数器的值 index
) 我们之前保存过。
0
(false) 在第二个参数上指定,表示 return 是一个值而不是指针。