[sharing] efficient app.DoEvents replacement

  1. 8 months ago
    Edited 8 months ago

    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?

    I solved this issue by creating a simple Linux plugin to provide delay function. Now, average CPU usage is 10.0%.

    Thank you all. I'll create feedback for this issue.

  2. Thom M

    12 Feb 2018 Pre-Release Testers Greater Hartford Area, CT

    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.

  3. Michel B

    12 Feb 2018 Pre-Release Testers RubberViews.com
    Edited 8 months ago

    @AsisPatisahusiwa Using do...loop
    Wrap the code inside a Thread and call App.SleepCurrentThread
    However, both solutions will cause high CPU usage.

    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.

  4. @Michel B The loop will burn CPU. Not App.SleepCurrentThread.

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

    @Michel B 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 ?

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

  5. Michel B

    13 Feb 2018 Pre-Release Testers RubberViews.com

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

    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.

  6. 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%.

  7. 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
  8. Julian S

    13 Feb 2018 Pre-Release Testers, Xojo Pro UK

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

  9. Edited 8 months ago

    @Julian S 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.

  10. Michel B

    13 Feb 2018 Pre-Release Testers RubberViews.com
    Edited 8 months ago

    [quote=373344:@AsisPatisahusiwa]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.

  11. Julian S

    13 Feb 2018 Pre-Release Testers, Xojo Pro UK

    @AsisPatisahusiwa 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

    You just need to be a little creative:

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

  12. Julian S

    13 Feb 2018 Pre-Release Testers, Xojo Pro UK
    Edited 8 months ago

    @AsisPatisahusiwa Yes, It's empty project. Linux OS.

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

  13. Thom M

    13 Feb 2018 Pre-Release Testers Greater Hartford Area, CT

    @AsisPatisahusiwa 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

    So you need your XojoScript to count like a clock?

  14. @Thom M 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.

  15. Thom M

    13 Feb 2018 Pre-Release Testers Greater Hartford Area, CT

    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.

  16. Julian S

    13 Feb 2018 Pre-Release Testers, Xojo Pro UK

    @AsisPatisahusiwa Every user can type their void setup and void loop code.

    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.

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

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

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

  18. Michael D

    13 Feb 2018 Pre-Release Testers, Xojo Pro

    @AsisPatisahusiwa Yes, It's empty project. Linux OS.

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

  19. Tim P

    13 Feb 2018 Pre-Release Testers feedback://46303,51561
    Edited 8 months ago

    @Michael D 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

    @AsisPatisahusiwa // how can I cut this out and do a looping inside a timer without resetting x

    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.

  20. Newer ›

or Sign Up to reply!