RFC: AhkThread() usage + best practices suggestions Topic is solved

Post AHK_H specific scripts & libraries and discuss the usage and development of HotKeyIt's fork/branch
User avatar
Kintaro-OEx
Posts: 12
Joined: 17 Apr 2018, 15:48

RFC: AhkThread() usage + best practices suggestions

Post by Kintaro-OEx » 20 Nov 2020, 19:55

hey there friends!

further below you will find a working code which uses AhkThread() to start 2 independent infinite loops which are only doing work if a certain variable (namely) object.error is set to none.

If either of those loops encounter a problem -> object.error is changed and both loops will stop doing work!

the main thread recognizes the error message and cleans up/fixes the issue/whatever and eventually will change object.error to none again so the 2 threads/infinite loops will do work again.

I hope this short explanation is clear enough ^^ .

-----

I would like to know if my first approach is "correct" in terms of the AhkThread() usage and maybe there is even a "better" way of doing this idea/tasks of my use case for this first approach?!

I also would love to know how to use AhkThread() with a clear separation of the FUNCTION declaration and definition?!
SPEUDOCODE example: AhkThread( _THREAD_A() , parameter_A, paramater_B, etc.... )

I tried the "ScriptIsFile" parameter but no chance it seems. Would love to see a simple example so I can move on from there if that is possible.

In any case, thanks for your time if you did read that far!

Code: Select all

#NoEnv
#Persistent
#SingleInstance FORCE

STATE 		:= CriticalObject()
STATE.Value := "startup_clean"
STATE.error	:= "none"

__THREAD_A := AhkThread("
(
Sleep 2000
		object:=CriticalObject(" (&STATE) ")
	Loop{
		if(object.error = ""none""){
			Sleep 400
			object.VALUE:=""do A""
			
			if( A_Index = 20 ){
				object.error := ""error from A""
			}

		}
	Sleep 400
	}

)")

__THREAD_B := AhkThread("
(
Sleep 2000
		object:=CriticalObject(" (&STATE) ")
	Loop{
		if(object.error = ""none""){
			Sleep 800
			object.VALUE:=""do B""
			
			if( A_Index = 4 ){
				object.error := ""error from B""
			}
		}

	Sleep 800
	}

)")


Loop{
	
	; MAIN THREAD here
	; in case a THREAD reports an error back to "STATE.error" , error handling will be done here
	; after solving the issue "STATE.error" will be set back to "none" and the THREADS will continie the INFINITE LOOP like before
	
	ToolTip % STATE.VALUE "`n" STATE.error
		Sleep 50
	if(STATE.error != "none"){
		STATE.Value := "fixing the issue"
	}
}


Esc::ExitApp

F1::STATE.error	:= "error"
F2::STATE.error	:= "none"

kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: RFC: AhkThread() usage + best practices suggestions

Post by kyuuuri » 20 Nov 2020, 21:04

Hello, here are a few tips to improve your code's performance, readability, etc.
  • You can use a variable / file for ahkThread so instead of writing the code as a continuation section (which has limitations like size, escaping, etc.) you can write it on another file. If you don't like the idea of having multiple files, you can use another file but instead of writing the code as a normal script, you declare a variable with the code inside and do #include at the start of the main .ahk, then you pass this variable to ahkThread()
  • Remember that the directives on the main script are not shared with the threads, you need to write the directives again on each thread. You can use a file/variable for this and concatenate them on ahkThread(). Example: ahkThread(var_containing_directives "`n" var_containing_script)
  • You can use ahkPostFunction() to execute a function on the sub threads, this will be use less resources because you won't have a loop running all the time. And I think it would be a better approach for this case.

User avatar
Kintaro-OEx
Posts: 12
Joined: 17 Apr 2018, 15:48

Re: RFC: AhkThread() usage + best practices suggestions

Post by Kintaro-OEx » 20 Nov 2020, 21:20

kyuuuri wrote:
20 Nov 2020, 21:04
Hello, here are a few tips to improve your code's performance, readability, etc.
  • You can use a variable / file for ahkThread so instead of writing the code as a continuation section (which has limitations like size, escaping, etc.) you can write it on another file. If you don't like the idea of having multiple files, you can use another file but instead of writing the code as a normal script, you declare a variable with the code inside and do #include at the start of the main .ahk, then you pass this variable to ahkThread()
  • Remember that the directives on the main script are not shared with the threads, you need to write the directives again on each thread. You can use a file/variable for this and concatenate them on ahkThread(). Example: ahkThread(var_containing_directives "`n" var_containing_script)
  • You can use ahkPostFunction() to execute a function on the sub threads, this will be use less resources because you won't have a loop running all the time. And I think it would be a better approach for this case.
Thank you very much for the quick response!

I am trying the following to use multiple files, which should be the best approach maybe:

change to my code:

Code: Select all

__THREAD_A := AhkThread("threadA.ahk", , true)
threadA.ahk

Code: Select all

Sleep 2000
		object:=CriticalObject(" (&STATE) ")
	Loop{
		if(object.error = "none"){
			Sleep 400
			object.VALUE:="do A"
		}
		if( A_Index = 30 ){
			object.error := "error from A"
		}
	Sleep 400
	}
Error Message:
https i.imgur.com /hmjPd1f.png Broken Link for safety

How do I pass through the criticalObject then ^^ ?

cheers mate

HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: RFC: AhkThread() usage + best practices suggestions  Topic is solved

Post by HotKeyIt » 20 Nov 2020, 21:47

You do it via Parameters: __THREAD_A := AhkThread("threadA.ahk", "" (&STATE), true) and then object:=CriticalObject(A_Args.1*1)

User avatar
Kintaro-OEx
Posts: 12
Joined: 17 Apr 2018, 15:48

Re: RFC: AhkThread() usage + best practices suggestions

Post by Kintaro-OEx » 20 Nov 2020, 22:27

HotKeyIt wrote:
20 Nov 2020, 21:47
You do it via Parameters: __THREAD_A := AhkThread("threadA.ahk", "" (&STATE), true) and then object:=CriticalObject(A_Args.1*1)
I really appreciate your work here and your help towards my goal!
Your solution works perfectly.

....but one more thing, how would i learn that "A_Args.1*1" is correct if not from your help here. I mean how would I lookup that alone?

I totally understand " A_Args.1 " but the " *1 " after that :-D ?!?!

kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: RFC: AhkThread() usage + best practices suggestions

Post by kyuuuri » 20 Nov 2020, 22:53

Also you can read the file, put it into a variable and add the critical object declaration before the script. Then you use this variable to start the thread.
This example is only a representation of what you can do (I don't remember the syntax of fileread, and I didn't provide script_ahk)

Code: Select all

fileread, script_file, script.ahk
script_var := "object:=CriticalObject(" &STATE ")"
script_var .= "`n" script_file
ahkThread(script_var)

User avatar
Kintaro-OEx
Posts: 12
Joined: 17 Apr 2018, 15:48

Re: RFC: AhkThread() usage + best practices suggestions

Post by Kintaro-OEx » 20 Nov 2020, 23:28

kyuuuri wrote:
20 Nov 2020, 22:53
Also you can read the file, put it into a variable and add the critical object declaration before the script. Then you use this variable to start the thread.
This example is only a representation of what you can do (I don't remember the syntax of fileread, and I didn't provide script_ahk)

Code: Select all

fileread, script_file, script.ahk
script_var := "object:=CriticalObject(" &STATE ")"
script_var .= "`n" script_file
ahkThread(script_var)
fully understood, thanks again!

cheers mate!

HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: RFC: AhkThread() usage + best practices suggestions

Post by HotKeyIt » 21 Nov 2020, 07:41

I just tested and A_Args.1*1 is not necessary, normally it would convert string to number but this seems to happen anyway since a number is required.

User avatar
Kintaro-OEx
Posts: 12
Joined: 17 Apr 2018, 15:48

Re: RFC: AhkThread() usage + best practices suggestions

Post by Kintaro-OEx » 21 Nov 2020, 09:56

HotKeyIt wrote:
21 Nov 2020, 07:41
I just tested and A_Args.1*1 is not necessary, normally it would convert string to number but this seems to happen anyway since a number is required.
aaaaah okay, this a bit tricky in the end :-D. thanks for that clarification!

Post Reply

Return to “AutoHotkey_H”