Touch Develop retirement postponed until June 22, 2019. Sign-in and access to cloud assets to be removed on May 23, 2018.Learn More..


async actions

async keyword is used to execute an action in background.

atomic vs non-atomic

TouchDevelop APIs are either atomic or non-atomic. When you call a non-atomic API there is a little clock (stopwatch) symbol on the left. This indicates that the operation may take some time to complete. Most APIs are atomic, the ones that are not usually need to interact with the web (for example, web→download or bazaar→ast of), or just wait for something (time→sleep). The actions you define can be also atomic or non-atomic.

foreground vs background

TouchDevelop always executes at most one foreground task at a time. A foreground task is either the main action of a script or an event handler, for example one executed in response to box taps, shaking the device, tapping the board, and also timers (which can be attached to a board or be global).
While a foreground task is executing, the pages are not refreshed. Also, when the page is out of sync with the data (for example, an event handler writes some global data, and then sleeps, preventing the page from refresh), the page will ignore tap interactions coming from the user.
The only way to start a background task is to use the async keyword. You can place it in front of non-atomic API calls, and also in front of non-atomic actions. Actions are currently atomic by default, you can change that with the 'atomic' action check box which shows when you tap on the action name.
Any action can use async keyword, but actions marked with atomic cannot call non-atomic APIs without the async keyword. Non-atomic actions are ones that can take a long time, but if you put async keyword in front of it, it runs in the background and therefore takes no time. See below for discussion of atomicity of page display/init sections.

example

private function
download example
()
 example content := web → download("http://example.com/")
end function
page
download page
()
data
initialize
 example content := "nothing yet"
display
("Content: " example content) → post to wall
 controls → button("download", tapped)
where tapped() is
async  download example
end
end
 controls → button("ding!", tapped2)
where tapped2() is
 Ding → play
end
end
end page
Without async in front of download example, after you tap download but before the data has downloaded, tapping ding! would produce no sound. With async the dinging works as expected.

preventing multiple downloads

However, there is a catch. If you keep pressing download you will now start multiple background downloads. Sometimes this may be what you want, but sometimes you will need to actively work against it, for example by disabling the button, after the data starts downloading like this:
page
download page once
()
data
initialize
 example content := "nothing yet"
 data downloading := false
display
("Content: " example content) → post to wall
if not  data downloading then
 controls → button("download", tapped)
where tapped() is
 data downloading := true
async  download example
end
end
else ... end if
 controls → button("ding!", tapped2)
where tapped2() is
 Ding → play
end
end
end page
If you want re-enable the button, you will need to add:
 data downloading := false
at the end of download example. Note that, if you instead changed the body of the handler to be:
 controls → button("download", tapped)
where tapped() is
 data downloading := true
async  download example
**wrong!** will not disable the button
 data downloading := false
end
end
This would not have the desired effect. We would first set data downloading to false, start the download, and immediately change it back to true. In other words, the button would not hide.

watch for changing globals!

Whenever there is the clock symbol in the code (that is you're calling a non-atomic API), there is a chance that a background task will execute a bit. For example:
private function
wait and update
()
time → sleep(1)
 a := 2
end function
function
globals changing
()
var task := async  wait and update
 a := 1
(*) no interleave here
 a → post to wall
time → sleep(2)
 a → post to wall
end function
The code above will print 1 and then 2. While the sleep(2) is executing, the wait and update gets a chance to finish and update a. Note that there is no chance for it to run in the line marked with (*) (regardless of how short the sleep in wait and update would be), because there is no clock symbol next to this line.
To reiterate - the global variables may change in the background only when there is a clock symbol next to the line.

page display and init sections

Page init section can freely call non-atomic APIs and use the async keyword. Page display section cannot, it can only call atomic APIs, otherwise you get a compile-time error. If it calls a non-atomic action (for example from library) you will get a compile-time warning. Then, if that action calls a non-atomic API, you will get a run time exception.
If you get this warning for a call to action in your own script, use the make atomic button in the script properties. It will make as many actions as possible atomic.
If the call goes to a library, see if there is an update to the library, and if not go edit library and use the make atomic button on the library.
Calls to pages (with push keyword) are always treated as atomic. This is because the call itself doesn't do anything. The init and display code will be only executed later.

async keyword and Task→await API

So far we've been just calling non-atomic APIs with or without async keyword. When you use async keyword, you get a Task object back. The Task→await API (which is non-atomic) lets you wait for the task to finish. For example:
var task0 := async time → sleep(1)
var task1 := async time → sleep(1)
task0 → await
task1 → await
This code will sleep for about 1 second. The two sleep operations will be started in parallel, and by the time you're done waiting for task0, the task1 will be also finished, so there will be no waiting time.
async returns an object called Task. In case of time→sleep it's Task of Nothing because time→sleep has no useful return value. But for example for t := async web→download(...) returns a Task of String, and then t→await would return a String. All Task objects have →completed property, which lets you check if →await on such a task would block or not. Additionally, →await at most lets you place a time limit on the task. For example:
var dl task := async web → download("http://example.com/")
var downloaded string := dl task → await at most(5)
if dl task → completed then
if downloaded string → is invalid then
"download error" → post to wall
else
downloaded string → post to wall
end if
else
"timeout" → post to wall
end if
This code will be downloading from example.com for at most 5 seconds , and display "timeout" if the download doesn't finish in this time. Note that downloaded string is invalid if either the download failed or →await at most timed out, so we use →completed to distinguish between the two.

the special first await

When you call an async action, it will immediately execute uninterrupted until its first await statement. At this statement it will immediately pass control back to the caller.
Let's have a look at an example:
private function
update a twice
()
 a := 1
time → sleep(0.000001)
 a := 2
end function
function
test update first await
()
 a := 0
 b := 7
var task := async  update a twice
contract → assert( a = 1 and  b = 7, "")
task → await
contract → assert( a = 2 and  b = 7, "")
end function
When we call update a twice we know a := 1 will happen, but then it will hit await and return (regardless of how short the await may be). We also know that no other code will run, so we are sure that b stays 7.