Settimers are really useful
But to properly use them, we're going to learn the concept of threads
Here's a hotkey with a while loop
The idea is a toggle
You press the hotkey once, the tooltip starts following your mouse
Press it again: it disappears.
But it doesn't disappear, the hotkey doesn't work the second time
MaxThreadsPerHotkey fixes this, but it's much better to use a settimer instead
Now, the toggle is working as expected
Press once to enable, the second time to disable
Now, why does it suddenly work? Threads
Ahk is singlethreaded, meaning only one thing can be done at a time
While a line is executing, nothing else can be done in that moment
In other words, the thread is occupied
However!
While the interpreter is switching from one line to another, there's a time period when the thread is not occupied
Now it's not actually after every single line, more like every 16 milliseconds or so, depending on your CPU
This is because of how Windows works
It needs to disperse resources between all the numerous processes running at the same time
In those 16 milliseconds, windows checks for anything to do with a higher priority
It might not find anything, but the check will happen regardless
That's where settimers jump in
Once that check period is on, the settimer goes in between and executes whatever it needs to
So, instead of occupying the thread once it's completely free, it waits for the moment to interject into the thread that's currently running and does its thing
That's why a settimer that runs every millisecond is pretty much the same as 16 milliseconds
Because settimers wait for the nearest window they could jump into
So, they are limited in how often they can occupy the thread
Other precise methods to measure time are also limited in ahk, due to this same issue
When trying to test the time complexity of your function, you probably tried using TickCount
You didn't get precise results because the precision of TickCount is also about 16 milliseconds
So if you want to time your functions, you can either increase the input massively
Or use the dll call method that times a process
Don't ask me, I have no idea how to use it
Coming back to why the while loop method didn't work
The hotkey takes up the thread, and you can't use another hotkey while this one is in progress
Because once again, the thread is taken and only one thing can be done at a time
However, timers don't take up the thread as aggressively
Instead of taking it all for themselves, they say "Hey, I want to take the thread as soon as I can" Not as soon as literally now
That's what async is, at least in the context of ahk
And the only way to achieve this semi async, is using timers
Let's see how blocking the thread works in code
Here we have a function that returns zero the first 19 times it's called
Once you call it more than 19 times, it starts returning the number we've been incrementing
In the first scenario, we have a loop that keeps calling the function.
On the twentieth iteration,
It shows the first info and breaks
After that, we have the second info
And as you can see the order is how it's supposed to be
Here we have the same thing, but with a settimer instead
Even though we call the settimer first, when we run the script, the order is reversed.
This is because a timer does not occupy the thread
It basically says "run this function object at every next opportunity"
So, the "second" info runs before that first opportunity
This is big, as I'm sure you'll realize through trying out timers for yourself
Your understanding of threads is the most important knowledge for settimers
Right now we're going to get into the actual specifics
The first parameter of a settimer is a function object that you want to execute.
I go into detail on function objects in my video on them, as well as my video on arrow functions
Then you have your period in milliseconds.
Here, the function object will be called every second
If you specify a negative time, the timer will run only once, getting automatically deleted afterwards
If you have multiple timers, which one goes first will be decided by which is the closest in the timing
If it's the same, you can make one timer more important than the other using the third parameter: Priority
Although, you don't have to use it
When you want to delete a timer, meaning stop it, you specify 0 in its period
If the thread where you disable a timer was launched by a timer, you don't have to specify anything in the first parameter
However, if it's not, you have to specify the same function object in the first parameter
Even if your arrow functions are exactly the same, they won't work, because they actually resolve to different function objects in memory
If you want to use arrow functions, you'll have to extract it into a variable, and then use that variable
Same exact thing goes for the Bind method
But once again, not needed if the timer deletion is in a thread called by that same timer
That's about it on our tutorial on threads and settimers
I hope this video helped you clear up how both of those work
Have a good day :)