You can use the sync
expression to run two or more async expressions at the same time. For example:
# All three async functions effectively start at the same time
Results = sync:
AsyncFunction1() # task 1
AsyncFunction2() # task 2
AsyncFunction3() # task 3
# Called after all three tasks complete (regardless of order)
MyLog.Print("Done with list of results: {Results}")
The following code shows the syntax for the sync
expression with an accompanying diagram that shows the execution flow of the expressions.
expression0
sync:
slow-expression
mid-expression
fast-expression
expression1
Sync Expression Use
Where you can use a sync expression |
Async contexts |
Invocation time of the sync expression |
Async |
Requirements for sync code block |
The body of the sync expression must have at least two expressions that are async; otherwise, you have no need to run the expressions simultaneously. |
What the sync expression does |
Executes all expressions in its code block concurrently and waits for them all to finish before executing the next expression after the sync . |
When the sync expression completes |
When all the expressions in the sync code block have completed. |
When the next expression after sync starts |
When all the expressions in the sync code block have completed. |
Result of the sync expression |
Its result is a tuple of results from each expression in the order that the top-level expressions were specified. The result types of the expressions can be of any type, and each tuple element will have the type of its corresponding expression. |
At least two top-level expressions must be async.
sync:
AsyncFunction1()
MyLog.Print("Second top level expression")
AsyncFunction2()
MyLog.Print("Third top level expression")
sync:
AsyncFunction1()
# Error: expected at least two top-level expressions
Top-level expressions can be compound expressions, such as nested code blocks:
# sync may also have compound expressions
# with each top-level expression its own task
sync:
block: # task 1
# Evaluated in serial order
AsyncFunction1a()
AsyncFunction1b()
block: # task 2
AsyncFunction2a()
AsyncFunction2b()
AsyncFunction2c()
AsyncFunction3() # task 3
# AsyncFunction1a(), AsyncFunction2a() and AsyncFunction3() all start essentially at the same time
Since tuples can be used as self-splatting arguments, sync
expressions can be used directly as arguments since they have a tuple result. This allows async arguments to evaluate simultaneously, and the function they are being passed to is called when all the expressions in the sync code block are completed.
# All three coroutine arguments start their evaluation at the same time
DoStuff(sync{AsyncFunctionArg1(); AsyncFunctionArg2(); AsyncFunctionArg3()})
# Not every argument needs to be async - a minimum of two justifies the use of sync
DoOtherStuff(sync{AsyncFunctionArg1(); 42; AsyncFunctionArg2(); AsyncFunctionArg3()})