Sleep -1 Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Sleep -1

31 Dec 2017, 16:18

Edit: a better example here.

Hello

In the following simple example I have two threads running. What happens is that thread2 blocks thread1. I am trying to use Sleep -1 to force thread2 to hand execution back to thread1 after every loop iteration of thread2. Unfortunately it is not working. Any ideas? Thanks.

Code: Select all

SetWorkingDir %A_ScriptDir%
#Persistent

FileDelete , debug.txt
SetTimer, Thread1, 1000
sleep 500
SetTimer, Thread2, 1000
return


Thread1:
loop
{
	FileAppend , Thread 1`n , debug.txt
	sleep 1000
	sleep -1
}	
return


Thread2:
loop
{
	FileAppend , Thread 2`n , debug.txt
	sleep 1000
	sleep -1
	
}
return
My uneducated guess as to what is going on: sleep doesn't count as an "interruption" in the eyes of ahk, so sleep -1 inside thread2 doesn't hand it back to thread1 because thread1 is sleeping and therefore not interrupting.
Last edited by pneumatic on 31 Dec 2017, 17:59, edited 2 times in total.
User avatar
divanebaba
Posts: 816
Joined: 20 Dec 2016, 03:53
Location: Diaspora

Re: Sleep -1

31 Dec 2017, 16:55

Hi.
What sleep -1 does or not, I dont know, but I think your timer is overloaded.
With overloaded, I mean, the timer itself is triggered every second. The timer contains a loop, which repeat itself every second too. Before the loop repeats, the timer gets triggered again.
What ever you want to do, the code in the example will work, when you take the loop out.
Both timers had to look like below:

Code: Select all

Thread1:
	FileAppend , Thread 1`n , debug.txt
return
Einfach nur ein toller Typ. :mrgreen:
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: Sleep -1

31 Dec 2017, 17:12

divanebaba wrote: With overloaded, I mean, the timer itself is triggered every second. The timer contains a loop, which repeat itself every second too. Before the loop repeats, the timer gets triggered again.
I believe a Timer can only re-fire once it is complete, so it shouldn't be doing that. Adding some more debug lines seems to confirm it:

Code: Select all

Thread1:
FileAppend , Thread 1 starting`n, debug.txt
loop
{
	FileAppend , Thread 1`n , debug.txt
	sleep 1000
	sleep -1
}	
return

Thread2:
FileAppend , Thread 2 starting`n, debug.txt
loop
{
	FileAppend , Thread 2`n , debug.txt
	sleep 1000
	sleep -1
	
}
return

Result:

Code: Select all

Thread 1 starting
Thread 1
Thread 2 starting
Thread 2
Thread 2
Thread 2
Thread 2
Thread 2
Thread 2
Thread 2
Thread 2
Thread 2
Thread 2
Thread 2
Thread 2
Thread 2
The problem is I have a process detection thread timer which needs to go into a sleep loop once it detects a process. Then elsewhere in my script I have messageboxes which go into their own wait loops while waiting for user to click ok or cancel. The two clash and the messagebox wait loop gets blocked once a process is detected. For now I have avoided the situation by not allowing messageboxes while a process is detected, but it would be nice to forcibly hand over execution to underlying sleeping messagebox thread with a command such as sleep -1.
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: Sleep -1

31 Dec 2017, 17:24

Perhaps here is a more relevant example

Code: Select all

SetWorkingDir %A_ScriptDir%
#Persistent

FileDelete , debug.txt
SetTimer, Thread1, 1000
ShowMessageBox()
return


Thread1:
FileAppend , Thread 1 starting`n, debug.txt
loop
{
	FileAppend , Thread 1 firing`n , debug.txt
	sleep 1000
	sleep -1
}
	
return


ShowMessageBox(){

	loop
	{
		FileAppend , Messagebox is waiting for user to click a button`n , debug.txt
		sleep 2000
		sleep -1
	}

}
The result is the messagebox gets blocked

Code: Select all

Messagebox is waiting for user to click a button
Thread 1 starting
Thread 1 firing
Thread 1 firing
Thread 1 firing
Thread 1 firing
Thread 1 firing
Thread 1 firing
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: Sleep -1

31 Dec 2017, 17:32

I should mention, I can't put the messagebox wait loop into its own timer instead of a loop because it relies on local variables in order to identify the unique id of the messagebox that is waiting for user response, which only functions can provide, i.e I have tried a timer inside the function but it doesn't remember local variables between iterations of the timer.
User avatar
divanebaba
Posts: 816
Joined: 20 Dec 2016, 03:53
Location: Diaspora

Re: Sleep -1

31 Dec 2017, 17:44

pneumatic wrote:... I believe a Timer can only re-fire once it is complete, so it shouldn't be doing that. ...
I'm sorry to tell, that your mention is incorrect.
The parameter of the timer SetTimer, Thread1, 1000, in your case 1000 is the time that has to be passed, before the timer is triggered again.

A timer is like a loop, with the difference, that it repeats itself after a dedicated time.
Do not muddle an AHK timer with a timer for boiling eggs :mrgreen: :mrgreen:
Einfach nur ein toller Typ. :mrgreen:
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: Sleep -1

31 Dec 2017, 17:53

Well the debug text is showing that the timer doesn't fire again.

According to the documentation, Sleep -1 should force any pending interruptions to occur. However since the pending thread is sleeping, I presume this is not considered an interruption.

Here is an even simpler example

Code: Select all

SetWorkingDir %A_ScriptDir%
#Persistent

FileDelete , debug.txt
SetTimer, Thread1, 1000
sleep 3000  ;execution never gets past here because presumably sleep does not count as an interruption?   
MsgBox Hello world.
return


Thread1:
FileAppend , Thread 1 starting`n, debug.txt
loop
{
	FileAppend , Thread 1 firing`n , debug.txt
	sleep 1000
	sleep -1  ;should force any pending interruptions to occur
}
	
return
TygerByte
Posts: 96
Joined: 12 Aug 2016, 05:22

Re: Sleep -1  Topic is solved

31 Dec 2017, 18:25

The previous thread can't interrupt the current thread because you're in a loop. sleep -1 isn't a way out of the loop as far as I'm aware.
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: Sleep -1

31 Dec 2017, 18:28

TygerByte wrote:The previous thread can't interrupt the current thread because you're in a loop. sleep -1 isn't a way out of the loop as far as I'm aware.
Yeah I think you're right, it must be loop which doesn't allow interruptions, because I found it still gets blocked even when I remove the sleep from the previous thread:

Code: Select all

SetWorkingDir %A_ScriptDir%
#Persistent

FileDelete , debug.txt
SetTimer, Thread1, 1000
sleep 50
SetTimer, Thread2, 1000
return


Thread1:
FileAppend , Thread 1 starting`n, debug.txt
loop
{
	FileAppend , Thread 1`n , debug.txt	
}
return


Thread2:
FileAppend , Thread 2 starting`n, debug.txt
loop
{
	FileAppend , Thread 2`n , debug.txt
	sleep 1000
	sleep -1	
}
return
Result:

Code: Select all

Thread 1 starting
Thread 1
...
Thread 2 starting
Thread 2
Thread 2
Thread 2
...
(Thread 1 is now blocked, even though it isn't sleeping)
TygerByte
Posts: 96
Joined: 12 Aug 2016, 05:22

Re: Sleep -1

31 Dec 2017, 18:41

Actually Thread 2 can interrupt the loop of Thread 1. You just need to alternate priority of the timers somewhere.

Edit: I'm not entirely sure about this after trying to increase the priority.
Last edited by TygerByte on 31 Dec 2017, 19:15, edited 1 time in total.
User avatar
divanebaba
Posts: 816
Joined: 20 Dec 2016, 03:53
Location: Diaspora

Re: Sleep -1

31 Dec 2017, 19:00

If you still believe, that a timer run only once, look into help file, which says: "Causes a subroutine to be launched automatically and repeatedly at a specified time interval."

Here a thread with similar issue.
Einfach nur ein toller Typ. :mrgreen:
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: Sleep -1

31 Dec 2017, 19:08

divanebaba wrote:If you still believe, that a timer run only once
But the debug text shows that it does not interrupt itself, and the documentation seems to support that
https://autohotkey.com/docs/commands/SetTimer.htm wrote:Reliability: A timer might not be able to run as often as specified under the following conditions:
2.The timer subroutine itself takes longer than its own period to run
I am concerned about the word "might" though, because I need to be absolutely sure that a timer is not going to interrupt itself, otherwise my script is horribly broken! :facepalm:
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: Sleep -1

31 Dec 2017, 19:57

TygerByte wrote:Actually Thread 2 can interrupt the loop of Thread 1. You just need to alternate priority of the timers somewhere.

Edit: I'm not entirely sure about this after trying to increase the priority.
I think maybe the reason it doesn't work is because a line of code inside the timer's loop isn't an interrupt, so it can't interrupt whatever current thread is running, therefore it gets blocked until the current thread finishes (I guess this is what you originally said :lol: ).

So in my case the only way to fix it seems to convert the loop part of it into it's own separate timer. That way it will create an interrupt each time.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Marium0505 and 348 guests