Often you may want to something to happen after a certain amount of time has elapsed, or you may want something to happen every few minutes or seconds. To do that you use a command that should already be familiar to you: the send
command. This command has an optional in time
clause that will cause the message you send to be executed when that time period has elapsed.
Syntax:
send message to object in time
Where:
message
is the name of any valid command or message, including built-in and custom commands and messages, and
object
is a valid object reference (only needed if the object you are sending the message to is not in the current message hierarchy, or if you want to bypass intervening objects in the hierarchy,) and
time
is any valid time period in seconds, ticks or milliseconds.
Usage examples:
Play a system alert to signal the end of a timed test:
send "beep" to this card in 30 seconds
To automatically advance to the next card after a specified time period:
send "go to next card" to this card in 180 ticks
As useful as it is to execute a single action at some future time, the real power of send in time
comes when you want to continuously check or update some aspect of your stack.
Create a simple digital clock or timer on your card:
# In button "startTimer": on mouseUp updateTime end mouseUp # In the card script: on updateTime put the long time into field "timer" send "updateTime" to me in 500 milliseconds end updateTime
With calls like this problems can arise. Let's say you wanted to move on to another card where the timer was no longer required. When you go to the next card, there would most likely still be a message in the queue waiting to be sent, but since you are now on a card that doesn't have field "timer" on it, the updateTime handler would cause an error. So you need to cancel the pending message before you leave the card. For this there is the cancel
command:
Syntax: cancel queued message ID
The queued message ID
is a number that is automatically generated when you use the send in time
command. You can capture it by using the result
function, storing the ID in a global variable or custom property, then canceling it when you leave the card:
# In the card script: local messageID on updateTime put the long time into field "timer" send "updateTime" to me in 500 milliseconds put the result into messageID end updateTime on closeCard cancel messageID end closeCard
What if you have several messages in the queue and you want to cancel some or all of them when you leave the card? One way is to save each message ID in its own global variable, but that can rapidly become unwieldy. Another approach would be to save all queued message IDs in a single variable, on separate lines, then loop through the variable when you leave the card:
# In a button script global gStartSeconds on mouseUp put the seconds into gStartSeconds updateTime startCounting end mouseUp # In the card script global gStartSeconds local messageIDs on updateTime put the long time into field "timer" send "updateTime" to me in 500 milliseconds put the result & cr after messageIDs end updateTime on startCounting put the seconds - gStartSeconds into fld "counter" send "startCounting" to me in 30 ticks put the result & cr after messageIDs end startCounting on closeCard repeat for each line thisMsgID in messageIDs cancel thisMsgID end repeat put empty into messageIDs end closeCard
There is also a function, the pendingMessages
, that will return a list of all queued messages. Each line contains four items of information, the first item being the message ID. So if you wanted to kill all queued messages you could do this:
on closeCard -- "brute-force" method of canceling pending messages
repeat until the pendingMessages is empty
cancel item 1 of line 1 of the pendingMessages
end repeat
end closeCard
Put your new knowledge to work by doing the Timing Assignment. When you are finished copy it to the Homework Drop folder.