How do you do something every so often?
Last updated at 4:30 pm UTC on 14 January 2006
On December 26, 2003 Jimmie Houchin asked: How to do: something every: soOften?
I am wanting to call a method every certainTimeInterval. The other day I spent the afternoon browsing for the appropriate method to handle something like this. I found many different time, delay and event type messages but I didn't spot anything like this:
Cron do: [some activity] every: someTimeInterval
I may very well have overlooked what I was looking for. I can definitely put something together that works from what I saw. But is there a favored way to handle something like this in Squeak.
This lead to the discussion listed below.
From: Julian Fitzell Sent: Friday, December 26, 2003 5:23 PM
You could do:
[[(Delay forSeconds: 60) wait. some activity] repeat] fork
though I agree it would be nice to have a better mechanism for this.
From: Jimmie Houchin Sent: Friday, December 26, 2003 6:56 PM
Well until something better appears or I write something better. Does something like this look alright?
[self continue] whileTrue: [doSomething.
(Delay forSeconds: 60) wait].
I did this in a workspace/transcript for testing. Did fine, don't know how efficient it is but it did work.
continue := true.
ptime _ 0
ctime _ 0
secsDelay _ 0
[continue] whileTrue: [
ptime _ ctime.
ctime _ Time millisecondClockValue.
secsDelay _ ctime - ptime.
Transcript show: ctime asString, ': ', secsDelay asString ;cr.
(Delay forMilliseconds: 2000) wait].
From: How to save a parts bin Sent: Friday, December 26, 2003 7:06 PM
If you're using Morphic, you can use stepping (you can step other messages besides #step, and at different rates). Look at the methods whose names contain the string 'startStepping'.
Otherwise, you can do (as Julian suggested):
[ delay := Delay forSeconds: 123456.
[ delay wait. self doSomething ] repeat ] fork.
Remember that you should use synchronization of some sort (SharedQueues are the easiest to use) between threads (especially, you can't call any Morphic methods directly from a non-UI thread).
There is a way to communicate from background threads to Morphic, and it's called #addDeferredUIMessage: . I extended this with a SystemController subclass for the same purpose in MVC (as part of the ProcessBrowser).
From: Jimmie Houchin Sent: Friday, December 26, 2003 7:17 PM
Ned, This is for a web app. So no Morphic. I briefly browsed some of the stepping methods looking for ideas.
I don't remember if I had any. :) I will use the Delay as suggested.
From: Lex Spoon Sent: Tuesday, December 30, 2003 2:15 PM
The Delay is going to make your doSomething happen in a separate thread. Is that acceptable? You will need to put in locks or other synchronization, assuming that doSomething actually has something to do with what the main thread does.
There is no law that morphic has to be removed from your image just because there is a web server going. I have found it a nice architecture to drive your entire server from morphic step methods. You may lose a millisecond here or there, but most of the time a few milliseconds is nothing compared to the network delays.
But if you really do not want Morphic around, then you must have some main loop somewhere driving everything? So have that main loop do the checking for what time has passed. If you are using a framework to get the main loop, then perhaps lobby the framework author to add a step-like mechanism for you.
Overall, if you take either of the latter approaches, you will end up with everything happening in a single thread. Single-threaded programming makes debugging easier and tends makes the code simpler to begin with.
See also:Delayed execution of some code How to time out a method