[sharing] efficient app.DoEvents replacement

Obviously, there is a situation when we can’t use Timer to delay execution of a code. One example in my mind is coding in XojoScript.

Assuming, we have this code

while true
    // some code here
    delay(1000) // delay 1000ms
wend

Here, we have 2 solutions for delay function,

  1. Using do...loop
  2. Wrap the code inside a Thread and call App.SleepCurrentThread

However, both solutions will cause high CPU usage.

Does anybody have other efficient solutions?

The only correct answer is: don’t.

Xojo is event driven, you should use event to react to something happening instead of waiting for it to happen. The only acceptable way to wait is to use Self.Sleep(1000) inside a thread’s Run event, that will make the thread sleep for 1 second and resume on the next line.

[quote=373210:@Asis Patisahusiwa]Using do…loop
Wrap the code inside a Thread and call App.SleepCurrentThread
However, both solutions will cause high CPU usage.[/quote]

The loop will burn CPU. Not App.SleepCurrentThread.

About XojoScript, why specifically would you need to pause execution ? Even so, what prevents you to have a XojoScript for the beginning of execution, then a second XojoScript that will be launched from a timer Action event ?

As Thom just said, don’t use outdated waiting loops. This is typical of procedural thinking we used back in the eighties when we did not have events. Antiquated.

Try to wrap your head around timers and event programming. Once you have grasped the concept, you will realize how much cleaner and simple it can be.

Simple test shows high CPU usage is caused by thread sleep method.

I’ve considered this before. This will be the best solution if I can get my head around it.

This is not expected.

At any rate, I frankly think even that is not the best way to deal with delays. The real solution in an event driven programming is Timer. Timer does not burn CPU.

Simple test

//PushButton1
Sub Action() Handles Action
  Thread1.Run()
End Sub

//Thread1
Sub Run() Handles Run
  me.Sleep(100*1000)
End Sub

CPU usage: 75%.

This simple XojoScript code demonstrate why I can’t use timer.

dim x as Integer

// how can I cut this out and do a looping inside a timer without resetting x value each time?
while true
    x = x + 1
    Print str(x)
    delay(1000) // delay 1000ms
wend

That should not be happening, I assume its a brand new empty project, what platform is that on?

Yes, It’s empty project. Linux OS.

[quote=373344:@Asis Patisahusiwa]This simple XojoScript code demonstrate why I can’t use timer.

[code]

Look, if all you want to is to use tight loops, simply do it. No need to invent excuses.

[quote=373344:@Asis Patisahusiwa]This simple XojoScript code demonstrate why I can’t use timer.

[code]
dim x as Integer

// how can I cut this out and do a looping inside a timer without resetting x value each time?
while true
x = x + 1
Print str(x)
delay(1000) // delay 1000ms
wend
[/code][/quote]

You just need to be a little creative:

https://www.dropbox.com/s/icbdco168ypt23d/SleepTightLoopInsideXojoScript.xojo_binary_project?dl=1

You might want to put that in as a bug report then as a sleeping thread should not be burning CPU, ever.

[quote=373344:@Asis Patisahusiwa]This simple XojoScript code demonstrate why I can’t use timer.

[code]
dim x as Integer

// how can I cut this out and do a looping inside a timer without resetting x value each time?
while true
x = x + 1
Print str(x)
delay(1000) // delay 1000ms
wend
[/code][/quote]
So you need your XojoScript to count like a clock?

No. The closest example is writing Arduino code. Imagine I create my own Arduino environment. Every user can type their void setup and void loop code.

void setup()
{
  // ...
}

void loop()
{
  // ...
}

So, I need to execute void loop in a loop. Everything works fine except for high CPU usage when delay the looping.

Yeah, you definitely need to run that inside a thread. Create a thread, set the run event to something like

Do Script.Execute() Self.Sleep(1000) Loop

You should have no problem with that. Don’t use App.SleepCurrentThread if you’re already in a thread, that’s a waste since you already know which thread to sleep. Is it a big waste? No, probably not, but it is still a waste. I don’t think in all my years I’ve ever found a good use for App.SleepCurrentThread. Not saying a use case doesn’t exist, but I am saying its usage should be rare at best.

Don’t run the loop inside your XojoScript though, that’s going to be trouble.

I guess this in a web environment? You could use the example I posted and thread off a class1 for each user of the website, each xojoscript is self contained then.

Yes, I think I will stick with sleep method until I find a better solution.

This is weird. I hope I can find old xojo version with better thread performance.

That doesn’t happen on macOS or WIn32 - Please report it as a bug.

Indefinite while loops are known to spike cpu usage, I consider it one of the reasons to avoid them. To confirm the behavior, I just did it on my Mac

For this specific example subclassing would do the trick. Store x as a property and print it’s value in the Action event handler. Set the period as desired, and for extra accuracy confirm the time between prints before printing.

I am not sure XojoScript is available in a web app…