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

Viewed 743

I'm so lost. Isn't this possible?

What I need:

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---

What I have:

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")

This is what the documentation makes it look like how I'm supposed to do it. The message box shows random numbers that look a lot like pointers. Am I stupid?

Edit: If this isn't possible then what is the point of ahkassign and ahkgetvar? To me, the documentation for ahkgetvar certainly makes it look like you can execute a thread and then retrieve a variable from that thread.

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
1 Answers

I can't really make sense of what you're trying to do with your code, but I can answer the title of your question.

So first a little about the AHK_H v2 documentation, don't take it too seriously. It's really outdated, you'll easily get errors trying to run the example scripts, etc. The chm file that's provided is a bit better than the online documentation though.

Then about your script, the DllCalling doesn't seem to go too well, but better to just not use it.
There's no need for it.

Here's a full working script, I'll explain it below:

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))

So, first we create a critical object. This one is just going to be a simple object with one property, count.

Then we launch a new thread with ahkThread(). I took the approach of just writing the simple scripts out as plain text to the first parameter.
If you're not familiar with the

"
(
text
text
text
")

notation, this is what's called a continuation section.
It just saves us the headache of writing one long line with `ns.
Then for the second parameter (&MyObj ""), which passes a value to A_Args, as the documentation specifies, I pass in the pointer for our critical object MyObj (note that the & prefix to retrieve a pointer is not available in AHK v2, but is in AHK_H v2).
And also I concatenate the pointer with an empty string (basically casting it to string). This is just something you need to do to avoid it being automatically StrGet'd.

Inside the new thread we launched, we create a local variable index which is just going to count how many loops that thread has done.
And then we get our critical object again by referring to the pointer we passed into A_Args.
Then the loop just runs for as long as it does and increments both the global counter MyObj.count, and the local counter index.

The return value of the ahkThread() function is stored to the variable thread2 so we later use one of the many useful methods specified in the documentation.

Then we start another thread, just a copypaste of what we did above.
Then we sleep a random amount of time between 500 and 2000 ms.
Then we print a message box that shows the global counter, and the two local counters.
The local counters should add up to the global counter's value.

The local counters' values index are retrieved from the threads by using the .ahkgetvar() method on the thread objects (thread2 and thread3) we saved earlier.
0 (false) is specified on the second parameter to indicate returning a value instead of a pointer.

Related