AHK V2: Why does auto-execute thread get interrupted by timers...

Discuss the future of the AutoHotkey language
SAbboushi
Posts: 252
Joined: 08 Dec 2014, 22:13

AHK V2: Why does auto-execute thread get interrupted by timers...

03 Aug 2018, 15:38

Why does auto-execute thread get interrupted by timers if Critical statement is executed before any timer functions are called?

Code: Select all

#SingleInstance Force

global StartTime := A_TickCount

SetTimer "MsgBox1", -1
SetTimer "MsgBox2", -1,-1
SetTimer "MsgBox3", -1
						; Timers are enabled before auto-execute is set to Critical
Critical

global xxx:=1				; xxx = 1 proves that Critical statement was executed before timer function MsgBox1 is called;
						;	MsgBox1 interrupts auto-execute thread before msgbox "auto" below is executed

msgbox "auto`n+" ElapsedTime := A_TickCount - StartTime

Documentation says:
A critical thread will be interrupted ... 3) any callback indirectly triggered by the critical thread itself
Is this the explanation? If so, does that mean that the placement of Critical is not significant e.g. this script will behave the same whether or not Critical is placed before or after the SetTimer statements?
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

03 Aug 2018, 16:02

Critical wrote:A critical thread becomes interruptible when a MsgBox or other dialog is displayed.
SAbboushi
Posts: 252
Joined: 08 Dec 2014, 22:13

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

03 Aug 2018, 16:19

I don't see how that applies: if auto-execute is a critical thread, then it would need to be interrupted IN ORDER FOR MsgBox1 to display -- unless you're confirming that the timers are set to Critical even though they were (Edit: set enabled) before the Critical statement...?
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

03 Aug 2018, 16:34

It seems that most of your code in the example is missing.
Recommends AHK Studio
SAbboushi
Posts: 252
Joined: 08 Dec 2014, 22:13

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

03 Aug 2018, 16:49

I didn't post the functions called by the timers -- didn't think that was relevant to answer my question(s), but since I don't understand what's going on, maybe I'm mistaken!

Code: Select all

MsgBox1()
{
   
  MsgBox "M1`n+" ElapsedTime := A_TickCount - StartTime

  static j:=0
  j++
  gui:=guicreate(,"gui1")
  gui.Add("Text","w300 h300","TEXT111")
  gui.Show
  ;MsgBox "MsgBox1: " j
}

MsgBox2()
{
  gui:=guicreate(,"gui2")
  gui.Add("Text","w300 h300","TEXT222")
  gui.Show
 ; msgbox "MsgBox 2"
}

MsgBox3()
{
  gui:=guicreate(,"gui3")
  gui.Add("Text","w300 h300","TEXT333")
  gui.Show
  msgbox "MsgBox 3`n+" ElapsedTime := A_TickCount - StartTime
}

F5::
  ExitApp
SAbboushi
Posts: 252
Joined: 08 Dec 2014, 22:13

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

03 Aug 2018, 17:30

OK... now I'm more confused. I discovered the A_IsCritical command which looked like the way to answer my own question:

positioning Critical after the SetTimer statements did not set MsgBox1 thread to Critical.

However, positioning Critical before the SetTimer statements did not set MsgBox1 thread to Critical either... which seems to conflict with my understanding of the documentation:
if the auto-execute section turns on Critical but never turns it off, every newly launched thread (such as a hotkey, custom menu item, or timed subroutine) starts off critical
Since I understand MsgBox1 to be a "timed subroutine", I was expecting it to be launched as critical... but M1_critical = 0??

Code: Select all

#SingleInstance Force

global StartTime := A_TickCount, M1_critical := "abc"

Critical					; auto-execute thread set to Critical BEFORE Timers are enabled

A_critical := A_IsCritical  ; 16
						
SetTimer "MsgBox1", -1, 
SetTimer "MsgBox2", -1,-1
SetTimer "MsgBox3", -1

;Critical					; Timers are enabled before auto-execute is set to Critical

;Thread "NoTimers"


global xxx:=1               ; xxx = 1 proves that Critical statement was executed before timer function
                            ;   MsgBox1 is called;
                            ;	MsgBox1 often interrupts auto-execute thread before msgbox "auto" below is 
                            ;   executed

msgbox "auto`n+" ElapsedTime := A_TickCount - StartTime

;Thread "NoTimers", false    
   


MsgBox1()
{
  M1_critical := A_IsCritical   ;   0
  
  MsgBox "M1`n+" ElapsedTime := A_TickCount - StartTime

Entire script:
Spoiler
So my questions are:
What causes MsgBox1 timer thread to interrupt auto-execute thread if autoexecute thread is Critical and MsgBox1 thread is not?
Why isn't MsgBox1 thread Critical if Critical statement is before the SetTimer statements in auto-execute?
SAbboushi
Posts: 252
Joined: 08 Dec 2014, 22:13

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

03 Aug 2018, 18:53

Adding Sleep 100 between Critical and SetTimer statements results in M1_critical = 16. So this delay seems to determine whether or not the timer thread starts as Critical or not.

Hoping someone can clarify this (to me) confusing behavior and whether it contradicts the documentation reference I posted.
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

03 Aug 2018, 19:51

Search the Critical documentation for "MsgBox".
SAbboushi
Posts: 252
Joined: 08 Dec 2014, 22:13

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

03 Aug 2018, 23:23

Already done that-- and Helgef has already posted the one reference to MsgBox above. Both you and Helgef are telling me the same thing, but it's not making sense. It seems to me that the documentation differs from my testing:
A critical thread becomes interruptible when a MsgBox or other dialog is displayed
Further testing demonstrates that the auto-exec thread is indeed being interrupted after the interpreter evaluates the MsgBox line, but the interruption occurs BEFORE the "auto" MsgBox is displayed. The MsgBox "auto" (as I've been saying) doesn't display until after the Priority 0 timer threads end as demonstrated by the (spoiler) script below.

Maybe someone can clarify what this means if it doesn't mean that MsgBox "auto" should display before its thread is interruptable:
... when a MsgBox or other dialog is displayed
?

My testing suggests that MsgBox AuditTrail was displayed BECAUSE of the MsgBox "auto" statement, but MsgBox "auto" was NOT displayed when the Critical auto-execute thread was interruped.

Am I just being foolish here?
:headwall: :headwall:
Spoiler
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

03 Aug 2018, 23:51

I think you are reading too much into it. The key point is about which commands have this effect (commands which display a dialog), not about the exact moment at which it happens. You are clearly calling MsgBox, and this is making the thread interruptible.

The dialog is displayed by the standard MessageBox function (or various other functions for other dialogs). Once we call the function, control is out of our hands and in the hands of the OS; therefore, in order to mark the thread as interruptible, it must be done before the function is called. Consequently, the thread becomes interruptible when you call MsgBox, but before the dialog becomes visible. Any actual interruption will happen at whatever time the (hotkey, hotstring, GUI, menu, timer or whatever) message is pulled out of the message queue and dispatched. This is done by the message loop internal to the MessageBox function.

Think of "when the dialog is displayed" as the duration between when the system starts to display the dialog and the moment it stops routing messages to the dialog (after it closes). If the process of displaying the dialog is interrupted, it will not become visible at the expected time.

As for setting defaults in the auto-execute section,
auto-execute section wrote:If the auto-execute section takes a long time to complete (or never completes), the default values for the above settings will be put into effect after 100 milliseconds. When the auto-execute section finally completes (if ever), the defaults are updated again to be those that were in effect at the end of the auto-execute section.
SAbboushi
Posts: 252
Joined: 08 Dec 2014, 22:13

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

04 Aug 2018, 00:37

Thanks lexikos - that's the info I needed to understand what was going on!

re: setting defaults in the auto-execute section: I assume you're responding to my query
SAbboushi wrote:Adding Sleep 100 between Critical and SetTimer statements results in M1_critical = 16. So this delay seems to determine whether or not the timer thread starts as Critical or not.
I'm sorry, but I'm confused, maybe because the documentation refers to two kinds of default values:
1)
the default values for the following attributes as set in the auto-execute section

2)
If unset, the standard defaults will apply
So which of those two is being referred to in:
the default values for the above settings will be put into effect after 100 milliseconds
?
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

04 Aug 2018, 01:10

So which of those two is being referred to in
You already found out, by testing. I've seen confusion about this before, it should be clarified.

Also note that everything discussed here behaves the same in v1.
SAbboushi
Posts: 252
Joined: 08 Dec 2014, 22:13

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

04 Aug 2018, 01:30

Seems I must be somewhat dumb, because it's still not clear to me despite my testing:
If the auto-execute section takes a long time to complete (or never completes), the default values for the above settings will be put into effect after 100 milliseconds.
:crazy:

As best as I can tell (based upon my testing), this means: If I don't add Sleep 100 somewhere before the auto-execute MsgBox "auto", then it appears that because less than 100ms has passed since the script began that the timer threads use the "standard default" settings (i.e. not-Critical), even though I've specified Critical at the top of the auto-execute section -- but if I add Sleep 100, then the Critical statement in the auto-execute thread becomes the default for the timer threads... which doesn't make sense to me: because this suggests that "default values" I define in the auto-execute section (e.g. Critical) are ignored unless the auto-execute thread takes longer than 100ms to run??
SAbboushi
Posts: 252
Joined: 08 Dec 2014, 22:13

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

04 Aug 2018, 09:13

oops - let me ammend: ... which doesn't make sense to me: because this suggests to me that "default values" I define in the auto-execute section (e.g. Critical) are ignored not used as default settings for new threads unless the auto-execute thread takes longer than 100ms to run??
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

04 Aug 2018, 09:21

unless the auto-execute thread takes longer than 100ms to run??
...or has ended.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

04 Aug 2018, 09:48

- Just thought that the following would be worth a mention:
- IIRC you can do a Loop where you query the A_ variables to make sure they have been defined correctly, and use Sleep 100.
- I first became interested in Critical because I wanted to make a subroutine uninterruptible, to prevent any of the global variables from being altered by another subroutine. However, to my surprise, I found that there were exceptions to Critical e.g. MsgBox. I instead found that 'Thread, Priority' would give me the behaviour I wanted.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
SAbboushi
Posts: 252
Joined: 08 Dec 2014, 22:13

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

04 Aug 2018, 10:43

Helgef wrote:
unless the auto-execute thread takes longer than 100ms to run??
...or has ended.
I thought I finally understood it... that you were telling me the timer threads were created after the auto-execute thread had ended, which is why they started as the "standard default" non-critical... but I added

Code: Select all

Loop
  ToolTip xxx++
to the end of auto-execute section and timers were still started as non-critical if I don't insert Sleep 100 somewhere before MsgBox "auto", so I'm still confused...
jeeswg wrote:However, to my surprise, I found that there were exceptions to Critical e.g. MsgBox.
Just to confirm :crazy: (I'm still trying to understand all the pieces): You're referring to a MsgBox in the Critical thread, right?
jeeswg wrote:I instead found that 'Thread, Priority' would give me the behaviour I wanted.
Thanks -- I'll look into that. I started with Critical because the documentation says
Due to its ability to buffer events, the function Critical is generally superior to Thread "Priority".
So I guess it's pick one: uninterruptible or buffer events?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

04 Aug 2018, 12:00

- Re. 'I found that there were exceptions to Critical e.g. MsgBox.'
- When a thread is critical, you can't interrupt it. But there are exceptions e.g.
Critical - Syntax & Usage | AutoHotkey
https://www.autohotkey.com/docs//commands/Critical.htm
Prevents the current thread from being interrupted by other threads, or enables it to be interrupted.
...
A critical thread becomes interruptible when a MsgBox or other dialog is displayed. However, unlike Thread Interrupt, the thread becomes critical again after the user dismisses the dialog.
- Re.
Due to its ability to buffer events, the function Critical is generally superior to Thread "Priority".
- I forgot about this. If suddenly some ancient hotkeys are triggered ten minutes late, when a thread completes, that isn't 'superior' to me. So, another bit of surprising behaviour.

- Well, you could propose some feature requests. I've gotten used to things as they are pretty much.
- So, from my perspective, it would make sense if Critical meant critical, especially during MsgBox, and that buffering events is 'inferior'. But people are welcome to suggest opposing arguments. For me, granularity of control is often a good solution.
- Sometimes I do checks within hotkey subroutines to end them early.
- These might be useful:
#MaxThreads
#MaxThreadsBuffer
#MaxThreadsPerHotkey
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
SAbboushi
Posts: 252
Joined: 08 Dec 2014, 22:13

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

04 Aug 2018, 13:52

lexikos wrote:The key point is about which commands have this effect (commands which display a dialog), not about the exact moment at which it happens. You are clearly calling MsgBox, and this is making the thread interruptible.
For those who are confused like I was: Lexikos's response was helpful to make sense of my debugging sessions (i.e. I was expecting a MsgBox or multiple MsgBoxes to display but they didn't when I expected them to, AND they displayed out of order). So I've learned that if a new thread (e.g. timer thread) interrupts in less than 60ms (in my environment), that such a short "period" can interrupt a thread before it's had enough time to display the MsgBox.

So for my debugging sessions when I'm trying to see when/where threads are interrupted, instead of using periods of "-1", I'm using at least "-60" which gives enough time for MsgBoxes to display when I expect them to. This also helps the CallStack to make more sense.

jeeswg: thanks for your post. Gave me a useful different persepective to consider.

Still hoping someone will respond to:
SAbboushi wrote:
Helgef wrote:
unless the auto-execute thread takes longer than 100ms to run??
...or has ended.
I thought I finally understood it... that you were telling me the timer threads were created after the auto-execute thread had ended, which is why they started as the "standard default" non-critical... but I added

Code: Select all

Loop
  ToolTip xxx++
to the end of auto-execute section and timers were still started as non-critical if I don't insert Sleep 100 somewhere before MsgBox "auto", so I'm still confused...
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

04 Aug 2018, 14:13

Thread settings you set in the auto-execute section are ignored by new threads until, either the auto-execute section has ended or has been running for more than 100 ms.
Two examples,

Code: Select all

; Example 1
setkeydelay 37
dllcall f := callbackcreate('f')
dllcall f
f(){
	msgbox a_keydelay
}

Code: Select all

; Example 2
global t := a_tickcount
setkeydelay 37
settimer 'f', -1
; end auto-execute section
f(){
	msgbox a_keydelay "`n" a_tickcount-t
}
Cheers.

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: DaveT1 and 35 guests