Page 1 of 1

#MaxHotkeysPerInterval is exceeded, why?

Posted: 27 May 2020, 03:44
by Rohwedder
let this count to 123456

Code: Select all

SetKeyDelay, 500, 500
While GetKeyState("q","P")
	Send,% A_Index
;Sleep, 0
and there comes the error:
71 hotkeys have been received in the last 0ms …
The Sleep, 0 prevents this.

Re: #MaxHotkeysPerInterval is exceeded, why?

Posted: 21 Jun 2020, 01:18
by lexikos
Send does not allow thread interruption while it is sleeping, so all of your (key-repeat) hotkey activations are buffered until the next message check, which is either Sleep, 0 or after the thread finishes. All of the buffered hotkey activations are then processed at once, either being discarded because the thread is still running (with Sleep, 0) or triggering the warning because they all appear to be received at the same time.

If you disable the warning without enabling Sleep, 0, the hotkey will be called many times in a row after you release the key. You just won't notice it in this case because the subroutine does nothing when GetKeyState returns false.

Re: #MaxHotkeysPerInterval is exceeded, why?

Posted: 21 Jun 2020, 02:13
by Rohwedder
But why are the (key repeat) hotkey activations buffered?
#MaxThreadsPerHotkey 1
#MaxThreadsBuffer Off
Off: This is the default behavior.
A hotkey press will be ignored whenever that hotkey is already running its maximum number of threads (usually 1, but this can be changed with #MaxThreadsPerHotkey).

Re: #MaxHotkeysPerInterval is exceeded, why?

Posted: 21 Jun 2020, 05:52
by lexikos
As I said, it is because Send does not allow thread interruption.
If a hotkey is pressed or a custom menu item is selected while the current thread is uninterruptible, that event will be buffered.
Source: Thread - Syntax & Usage | AutoHotkey
It is the same effect as using Critical:

Code: Select all

i := 0, c := 0
#if ++c  ; Count the number of activations detected by the hook.
         ; (Assuming #If is only called once for each activation,
         ;  which is true in this case but might not be in others.)
ToolTip % ++i " " c
while A_TimeSinceThisHotkey < 5000
    WinExist("just wasting time")
; Critical Off
; Sleep, 0
If you hold the key down for a few seconds and then let go, the tooltip will increment every 5 seconds until all of the buffered messages have been processed.

Also note:
For example, if you accidentally press a hotkey twice, having this setting ON would cause that hotkey's subroutine to automatically run a second time if its first thread takes less than 1 second to finish (this type of buffer expires after 1 second, by design). Note that AutoHotkey buffers hotkeys in several other ways (such as Thread Interrupt and Critical). It's just that this particular way can be detrimental, thus it is OFF by default.
Source: #MaxThreadsBuffer - Syntax & Usage | AutoHotkey
It literally means #MaxThreadsBuffer only buffers up to one activation - it may run a second time. In this case, it repeats as many times as the key repeated - it's not related to #MaxThreadsBuffer.

As far as I am aware, "several other ways" really only means one other way (by leaving messages in the queue while a thread is uninterruptible), but there are multiple reasons for a thread to be uninterruptible.

It's not that hotkeys are being buffered specifically, but all posted messages with message number >= 0x312 (WM_HOTKEY) are left in the queue until the thread becomes interruptible. This includes other messages that start new threads (menu, GUI, etc.).

There was nothing in the documentation to indicate that Send is uninterruptible during the key delay, so I have added a line to the SetKeyDelay remarks. It also wasn't clear that "Behavior of Critical Threads" actually applies to all threads that are uninterruptible for any reason, so I have moved most of that section to the page for Threads. There also wasn't any list of reasons for the thread to be uninterruptible, so I have added one on the page for Threads.

See Thread Interruptibility (might need to force refresh).

I think that Send should remain uninterruptible, but to solve problems like yours, it can perform a short interruptible sleep in the specific case where the key delay is long enough to warrant it and the thread is not uninterruptible for some other reason. If the script wants to prevent interruption in between calls to Send, it should make the thread Critical.

Re: #MaxHotkeysPerInterval is exceeded, why?

Posted: 21 Jun 2020, 10:51
by Rohwedder
thanks for the detailed explanation and the additions to the manual.
Unfortunately I am not allowed to press the Accept this answer button in this forum anymore.
This button simply disappeared!

Re: #MaxHotkeysPerInterval is exceeded, why?

Posted: 21 Jun 2020, 16:37
by lexikos
It might be because you're in the Bug Reports forum. I'll mark it solved after I fix the bug.

Re: #MaxHotkeysPerInterval is exceeded, why?  Topic is solved

Posted: 01 Jul 2020, 03:33
by lexikos
Fixed in v1.1.33.00.

Re: #MaxHotkeysPerInterval is exceeded, why?

Posted: 01 Jul 2020, 03:52
by Rohwedder
Perfect! Thank you!