# How to run function every x seconds?

I want to make a Graphics with a Disk whose position should update every 4 seconds. This is what I've got so far:

RunScheduledTask[(cdts = RandomReal[{-5, 5}, 2]), 4]

{Framed[Graphics[{Yellow, Disk[Dynamic@cdts, 1]}, PlotRange -> 6,
ImageSize -> Large]], Dynamic@cdts}


I chose not to use Refresh because that evaluates way more than once every 4 seconds (I'd say every half second or so), even though I've set UpdateInterval-> 4, like so:

{Framed[Graphics[{Yellow,
Disk[Dynamic@Refresh[cdts, UpdateInterval -> 4], 1]},
PlotRange -> 6, ImageSize -> Large]], Dynamic@cdts}


From a previous question I asked, I think this is because Mathematica takes the UpdateInterval as a minimum, and so updates much more often when it can.

From what I've read in the documentation, RunScheduledTask should do exactly what I'm looking for, but it seems to update just as quickly as Refresh, about twice a second.

What am I doing wrong here?? I've been looking for quite a while now for a straightforward method to periodically run functions but none of them seem to work as advertised...

-
I cannot reproduce the problem with RunScheduledTask. Are you sure you do not have a couple of tasks running simultaneously? –  Michael E2 May 4 '14 at 13:18
@MichaelE2 this should be an answer :) –  Kuba May 4 '14 at 13:35
Your first code is fine. Dynamic updates only when the value of cdts is changed. Your observations are caused by not removing old ScheduledTasks. –  Kuba May 4 '14 at 13:47

You can also do what you want with a Trigger, which will perform real-time updates at reasonably accurate wall-clock intervals. Here is a jumping red disk that jumps every two seconds for 24 seconds.

center[_] := RandomReal[{-5, 5}, 2]
SeedRandom @ 42;
With[{nJumps = 12, jumpFreq = .5},
DynamicModule[{jump = 0},
Column[{
Dynamic@Framed[Graphics[{Red, Disk[center[jump], .5]}, PlotRange -> 6]],
Dynamic@Style[Row[{"Jump ", jump}], "SB"],
Trigger[Dynamic@jump, {0, nJumps, 1}, jumpFreq,
AppearanceElements -> {"PlayPauseButton", "ResetButton"}]}]]]


### Update

In response to a request in a comment, here is more information on the arguments and option I give to Trigger.

Trigger can take anywhere from one to three arguments. To get updates at a specified wall-clock rate, all three arguments must be specified. Trigger has attribute HoldFirst and the required first argument, must always be of the form Dynamic @ var; var will receive the ticks of the trigger's clock.

The second argument specifies the sequence of tick values given to var. It is a list having very much the same form as the argument sequence taken by Range. The argument variations that can be used for Range can be used for this argument. In the above example, {0, nJumps, 1} produces the tick sequence 0, 1, 2, ..., nJumps.

The third argument sets the clock frequency; a value of .5 Hz (as I used) is one tick every two seconds.

The standard appeareance elements for a Trigger are "TriggerButton", "PauseButton", and "ResetButton". The "TriggerButton" is actually a "ResetAndPlayButton". This means that a reset to zero is always performed when the "TriggerButton" is clicked, and there is no way to proceed from the paused state after the "PauseButton" is clicked. I don't like that behavior, so I used the AppearanceElements option to swap out the default set of controls and replace them with my own choices: "PlayPauseButton", and "ResetButton". With this set of controls, I can pause and then resume from where I paused.

-
That example is very useful, but could you possibly also just illustrate what Trigger does without the full example? In a fully worked example with lots of clutter it can be quite difficult to see exactly what is happening and why –  Aron May 4 '14 at 15:23
@Aron. This answer is already somewhat off target because it doesn't directly answer the question asked in this thread, but suggests an alternative approach. I think this is very close to a minimal working example that is still relevant to OP's problem. I will think about how I could edit it to satisfy your request without taking it further off target. –  m_goldberg May 4 '14 at 22:24
@Aron, Update made. Hope it satisfies you. –  m_goldberg May 5 '14 at 0:24
What makes you say Trigger "will perform real-time updates at precise intervals"? I think it's like most Dynamic things -- imprecise. –  Michael E2 May 5 '14 at 0:40
@MichaelE2. OK, I should have written (will change it to) "reasonably accurate". My example trigger ticks for 24 +/- 0.2 seconds when I time it with my mechanical Huer stopwatch. –  m_goldberg May 5 '14 at 0:52

With Refresh, you need to set TrackedSymbols :> {}; otherwise, the displayed graphics will be updated every time a variable changes, such as cdts as well as every 4 seconds.

{Framed[Graphics[{Yellow,
Disk[Dynamic@
Refresh[cdts, UpdateInterval -> 4, TrackedSymbols :> {}], 1]},
PlotRange -> 6, ImageSize -> Small]], Dynamic@cdts}


References:

@Aron The tutorials IntroductionToDynamic and AdvancedDynamicFunctionality are pretty much the required reading for understanding Dynamic. Even then, things can seem mysterious. In this case, however, it seems to work as described. –  Michael E2 May 4 '14 at 15:39