I have a list of ScheduledTask's to run in sequence one at a time. How can I set these to run in order so that the next one starts automatically after the previous one finishes?
2 Answers
Here is an example that will print 1, 2, 3, 4, 5 to the messages box (Window -> Messages) with a pause between each, even though they were scheduled to run at the same time.
StartScheduledTask /@ {
CreateScheduledTask[Print[5]; Pause[1], {2}],
CreateScheduledTask[Print[4]; Pause[3], {2}],
CreateScheduledTask[Print[3]; Pause[2], {2}],
CreateScheduledTask[Print[2]; Pause[5], {2}],
CreateScheduledTask[Print[1]; Pause[1], {2}]
}
You can change the length of the pauses to any number of seconds you want and it will still work. This shows that you don't have to know for how long the tasks you schedule will run.
-
-
$\begingroup$ @Kuba This is just "how it works" and it answers the question unless I am mistaken about what the OP wants which, of course, is possible. $\endgroup$– C. E. ♦Commented Apr 27, 2015 at 22:05
It's possible to run scheduled tasks in series by using the "EpilogFunction"
option for CreateScheduledTask
:
Clear[t1, t2]
t1 = CreateScheduledTask[Print["second"], {1, 10}]
t2 = CreateScheduledTask[Print["first"], {1, 5},
"EpilogFunction" :> StartScheduledTask[t1]]
StartScheduledTask[t2]
The code snippet above should print "first" to the message dialog 5 times in five seconds and then it starts scheduled task t1
upon completion, which prints "second" each second for 10 seconds.
Update
Here's perhaps a better example where the three tasks are daisy chained together and must be run consecutively in order to produce the desired result.
t1 = CreateScheduledTask[(x := {}; Clear[plot]), {1, 1},
"EpilogFunction" :> StartScheduledTask[t2]];
t2 = CreateScheduledTask[
AppendTo[x, RandomVariate[NormalDistribution[0, 1]]], {0.1, 100},
"EpilogFunction" :> StartScheduledTask[t3]];
t3 = CreateScheduledTask[plot = Histogram[x], {1, 1},
"EpilogFunction" :> (Print["done"];
RemoveScheduledTask@{t1, t2, t3})];
StartScheduledTask[t1]
will initialize the symbols for the next task, which simulates some time-intensive duty such as sensor reading. Once the task is completed, it calls a third task to do some processing of the data, followed by a message indicating that it is done. The routine also cleans up after itself by removing the task objects.
It's important to note that "EpilogFunction"
requires delayed rules (:>) to avoid premature execution and the option does not work with infinite loops. You need to explicitly state that your function will run once (e.g. {1,1}) however you do not need to know how long the task will take.
-
$\begingroup$ thanks your solution is great and very informative, i would feel guilty if I didn't acccept pickets answer because his was first and it is correct, even though I don't understand it. $\endgroup$– M.R.Commented Apr 30, 2015 at 22:48
StartScheduledTask /@ { CreateScheduledTask[Print[1], {2}], CreateScheduledTask[Print[2], {1}]}
. Or I missed the point? $\endgroup$StartScheduledTask /@ { CreateScheduledTask[Print[2], {1}], CreateScheduledTask[Print[1], {1}] }
, you scheduled them with different time intervals. But really I think my example in the chat is better. $\endgroup$Print
) evaluates so quickly that the tasks don't overlap, in which case there isn't a problem. Sequentially == one after another == queue == exactly what I'm demonstrating in chat. $\endgroup$