Age Old Question of "Pausing" Code (Michel B?)

Ok, call me dense, but even after going through the Forum (as well as guides and tutorials) and reading every reference I could find about “pausing” code I just can’t seem to grasp the concept of moving from the old procedural way of “pausing” a process to an event-based way of doing it. Don’t get me wrong, I’m well aware of the differences between procedural and event-based programming. However, this seemingly simple problem/task has me struggling for some reason.

Here’s the basic thing I need to do in my app and on multiple occasions:

  1. Trigger an event.
  2. Run some code.
  3. Update the UI with a graphic and text.
  4. Pause for 2 seconds.
  5. Update the UI with another graphic and text.
  6. Pause for 2 seconds.
  7. Update the UI with the final graphic and text.
  8. Pause for 2 seconds.
  9. Run some more code.
  10. Complete the event.

What am I missing? I’ve played around with timers, ticks, Xojo.Core.Timer.CallLater, etc., but I just can’t seem to achieve the desired result.

Any help would be appreciated. (Michel B, are you listening?) Thanks in advance. :slight_smile:

you could subclass a timer with a property of delay

when you start the timer, you set the delay you want and the current time (computed property)
in the timer action check the current time to see if your delay has expired yet and if it has
perform the action or raise an event

a version of this was used as a sort of stopwatch in some code i saw a long time ago.
to delay sending commands to a serial device
nicely re-usable and doesn’t mean you have loads of timers

Not sure what you have tried but here is a print out of a very basic example using a window with a timer control, a label, a push button and a property.

[code]Window1
Class Window1
Inherits Window
Private mTimerState_ As Int32

Window1 Control RunPushButton:
Sub Action()
Self.mTimerState_ = 0
Timer1.Mode = Timer.ModeMultiple
Timer1.Enabled = True
End Sub

Window1 Control Timer1:
Sub Action()
Dim caption As String
Self.mTimerState_ = Self.mTimerState_ + 1
Select Case Self.mTimerState_
Case 1
caption = “1st Action”
Case 2
caption = “2nd Action”
Case 3
caption = “3rd Action”
Case 4
caption = “Last Action”
Me.Enabled = False
End Select

Self.Label1.Text = caption
End Sub
End Class[/code]

Russ, Kevin, Thank you both for your quick replies.

Russ, that’s funny because that’s the next thing I was going to try.

Kevin, I did in fact come across that (or very similar) code and couldn’t determine if it would work or not for my particular issue.

I’ll try both of your suggestions and report back the first chance I get. Both will require me to rework some my code so it may be a while.

Thanks again. :slight_smile:

A Timer and a Thread are another option. Put your code into a Thread’s Run event. At certain intervals, update a property (or properties) with what you want to show in the UI and then sleep the thread for 2 seconds. A separate Timer grabs the property values and displays them in the UI.

Here’s a quick sample project: http://files.xojo.com/BlogExamples/PauseCode.xojo_binary_project

Be aware of this:

[code]Threads run in the background, but are temporarily blocked by certain user actions:

While the mouse button is held down,
While a window is being dragged,
While a menu in the menu bar is pulled down,
While the mouse button is pressed on a control in a window (not true of Windows)[/code]

If you need to do background processing which must continue, I’d prefer putting this code in a helper application.

Paul, That’s another great recommendation (and thanks for the sample code). I haven’t attempted to combine the two in the way you suggest. I’ll add it to my list of things to try.

Joost, Thanks for the heads-up. I’ll keep that in mind when deciding on the right solution.

:slight_smile:

Steven,

The best way I have found to go from procedural to event base is to use a timer any time I need to pause, at least when loops are not involved.

Here is your example :

  1. Trigger an event.
  2. Run some code.
  3. Update the UI with a graphic and text. // Best is to have a method
  4. Start a 2 seconds multiple timer AND RETURN FROM THE EVENT
    – > this goes in the Action event of the timer : Update the UI with another graphic and text.
  5. Pause for 2 seconds. // Taken care of by the timer
  6. Pause for 2 seconds. // Taken care of by the timer
    To count the number of times the timer triggered a refresh of the display, use a static variable which you increment each time the timer fires. When comes time to stop, something like this will do nicely :
me.mode = Timer.ModeOff
  1. Run some more code. – > That part is in the Action event of the timer, executes when the number of times it has executed in the static variable is OK.

http://documentation.xojo.com/api/language/static.html

Success!!! I just wanted to report back and let everyone know that I achieved the desired result. I took what I learned from your comments (and examples) and came up with a solution that uses a timer, thread, method, and global property as an array. It seems a little clunky so I’m sure I’ll go back and simplify/refine the solution over time. But, for now, it works!

[Joost, I don’t have to worry about the UI interfering with the thread at the moment. Though, if at some point I do, I’ll keep your warnings in mind.]

Thank you all again for your assistance. I’m happy to find that Xojo has such a supportive developer’s community. :slight_smile: