Async/await
Asynchrony and awaiting feature in programming languages
- 35 min read
- 4 chapters
Related on Lably
Through Computer programming, Function (computer programming) and Data structure
It is semantically related to the concept of a coroutine and is often implemented using similar techniques, and is primarily intended to provide opportunities for the program to execute other code while waiting for a long-running, asynchronous task to complete, usually represented by promises or similar data structures. The feature is found in C#, C++, Python, F#, Hack, Julia, Dart, Kotlin, Rust, Nim, JavaScript, and Swift.
History
F# added asynchronous workflows with await points in version 2.0 in 2007. This influenced the async/await mechanism added to C#.
Haskell lead developer Simon Marlow created the async package in 2010.
Microsoft first released a version of C# with async/await in the Async CTP (2011). It was later officially released in C# 5 (2012).
Python added support for async/await with version 3.5 in 2015 adding 2 new keywords, async and await.
TypeScript added support for async/await with version 1.7 in 2015.
JavaScript added support for async/await in 2017 as part of ECMAScript 2017 JavaScript edition.
Rust added support for async/await with version 1.39.0 in 2019 using the async keyword and the .await postfix operator, both introduced in the 2018 edition of the language.
C++ added support for async/await with version 20 in 2020 with 3 new keywords co_return, co_await, co_yield.
Swift added support for async/await with version 5.5 in 2021, adding 2 new keywords async and await. This was released alongside a concrete implementation of the Actor model with the actor keyword which uses async/await to mediate access to each actor from outside.
Sign in to keep reading
3 more chapters are free with a Lably account.
Example
The C# function below, which downloads a resource from a URI and returns the resource's length, uses this async/await pattern:
<span id="mwfQ"></span><span class="k" id="mwfg">using</span><span class="w" id="mwfw"> </span><span class="nn" id="mwgA">System</span><span class="p" id="mwgQ">;</span> <span class="k" id="mwgg">using</span><span class="w" id="mwgw"> </span><span class="nn" id="mwhA">System.Net.Http</span><span class="p" id="mwhQ">;</span> <span class="k" id="mwhg">using</span><span class="w" id="mwhw"> </span><span class="nn" id="mwiA">System.Threading.Tasks</span><span class="p" id="mwiQ">;</span> <span class="k" id="mwig">public</span><span class="w" id="mwiw"> </span><span class="k" id="mwjA">async</span><span class="w" id="mwjQ"> </span><span class="n" id="mwjg">Task</span><span class="o" id="mwjw"><</span><span class="kt" id="mwkA">int</span><span class="o" id="mwkQ">></span><span class="w" id="mwkg"> </span><span class="n" id="mwkw">FindSizeOfPageAsync</span><span class="p" id="mwlA">(</span><span class="n" id="mwlQ">Uri</span><span class="w" id="mwlg"> </span><span class="n" id="mwlw">uri</span><span class="p" id="mwmA">)</span><span class="w" id="mwmQ"> </span> <span class="p" id="mwmg">{</span> <span class="w" id="mwmw"> </span><span class="n" id="mwnA">HttpClient</span><span class="w" id="mwnQ"> </span><span class="n" id="mwng">client</span><span class="w" id="mwnw"> </span><span class="o" id="mwoA">=</span><span class="w" id="mwoQ"> </span><span class="k" id="mwog">new</span><span class="p" id="mwow">();</span> <span class="w" id="mwpA"> </span><span class="kt" id="mwpQ">byte</span><span class="p" id="mwpg">[]</span><span class="w" id="mwpw"> </span><span class="n" id="mwqA">data</span><span class="w" id="mwqQ"> </span><span class="o" id="mwqg">=</span><span class="w" id="mwqw"> </span><span class="k" id="mwrA">await</span><span class="w" id="mwrQ"> </span><span class="n" id="mwrg">client</span><span class="p" id="mwrw">.</span><span class="n" id="mwsA">GetByteArrayAsync</span><span class="p" id="mwsQ">(</span><span class="n" id="mwsg">uri</span><span class="p" id="mwsw">);</span> <span class="w" id="mwtA"> </span><span class="k" id="mwtQ">return</span><span class="w" id="mwtg"> </span><span class="n" id="mwtw">data</span><span class="p" id="mwuA">.</span><span class="n" id="mwuQ">Length</span><span class="p" id="mwug">;</span> <span class="p" id="mwuw">}</span>- First, the
asynckeyword indicates to C# that the method is asynchronous, meaning that it may use an arbitrary number ofawaitexpressions and will bind the result to a promise. - The return type,
System.Threading.Tasks.Task<T>, is C#'s analogue to the concept of a promise, and here is indicated to have a result value of typeint. (Note that when returning avoid, theSystem.Threading.Tasks.Taskclass is type-parameterless. - The first expression to execute when this method is called will be
new HttpClient().GetByteArrayAsync(uri), which is another asynchronous method returning aTask<byte[]>. Because this method is asynchronous, it will not download the entire batch of data before returning. Instead, it will begin the download process using a non-blocking mechanism (such as a background thread), and immediately return an unresolved, unrejectedTask<byte[]>to this function. - With the
awaitkeyword attached to theTask, this function will immediately proceed to return aTask<int>to its caller, who may then continue on with other processing as needed. - Once
GetByteArrayAsync()finishes its download, it will resolve theTaskit returned with the downloaded data. This will trigger a callback and causeFindPageSizeAsync()to continue execution by assigning that value todata. - Finally, the method returns
data.Length, a simple integer indicating the length of the array. The compiler re-interprets this as resolving theTaskit returned earlier, triggering a callback in the method's caller to do something with that length value.
A function using async/await can use as many await expressions as it wants, and each will be handled in the same way (though a promise will only be returned to the caller for the first await, while every other await will utilize internal callbacks). A function can also hold a promise object directly and do other processing first (including starting other asynchronous tasks), delaying awaiting the promise until its result is needed. Functions with promises also have promise aggregation methods that allow the program to await multiple promises at once or in some special pattern (such as C#'s Task.WhenAll(), which returns a valueless Task that resolves when all of the tasks in the arguments have resolved). Many promise types also have additional features beyond what the async/await pattern normally uses, such as being able to set up more than one result callback or inspect the progress of an especially long-running task.
In the particular case of C#, and in many other languages with this language feature, the async/await pattern is not a core part of the language's runtime, but is instead implemented with lambdas or continuations at compile time. For instance, the C# compiler would likely translate the above code to something like the following before translating it to its IL bytecode format:
<span id="mwARs"></span><span class="k" id="mwARw">using</span><span class="w" id="mwAR0"> </span><span class="nn" id="mwAR4">System</span><span class="p" id="mwAR8">;</span> <span class="k" id="mwASA">using</span><span class="w" id="mwASE"> </span><span class="nn" id="mwASI">System.Net.Http</span><span class="p" id="mwASM">;</span> <span class="k" id="mwASQ">using</span><span class="w" id="mwASU"> </span><span class="nn" id="mwASY">System.Threading.Tasks</span><span class="p" id="mwASc">;</span> <span class="k" id="mwASg">public</span><span class="w" id="mwASk"> </span><span class="n" id="mwASo">Task</span><span class="o" id="mwASs"><</span><span class="kt" id="mwASw">int</span><span class="o" id="mwAS0">></span><span class="w" id="mwAS4"> </span><span class="n" id="mwAS8">FindSizeOfPageAsync</span><span class="p" id="mwATA">(</span><span class="n" id="mwATE">Uri</span><span class="w" id="mwATI"> </span><span class="n" id="mwATM">uri</span><span class="p" id="mwATQ">)</span><span class="w" id="mwATU"> </span> <span class="p" id="mwATY">{</span> <span class="w" id="mwATc"> </span><span class="n" id="mwATg">HttpClient</span><span class="w" id="mwATk"> </span><span class="n" id="mwATo">client</span><span class="w" id="mwATs"> </span><span class="o" id="mwATw">=</span><span class="w" id="mwAT0"> </span><span class="k" id="mwAT4">new</span><span class="p" id="mwAT8">();</span> <span class="w" id="mwAUA"> </span><span class="n" id="mwAUE">Task</span><span class="o" id="mwAUI"><</span><span class="kt" id="mwAUM">byte</span><span class="p" id="mwAUQ">[]</span><span class="o" id="mwAUU">></span><span class="w" id="mwAUY"> </span><span class="n" id="mwAUc">dataTask</span><span class="w" id="mwAUg"> </span><span class="o" id="mwAUk">=</span><span class="w" id="mwAUo"> </span><span class="n" id="mwAUs">client</span><span class="p" id="mwAUw">.</span><span class="n" id="mwAU0">GetByteArrayAsync</span><span class="p" id="mwAU4">(</span><span class="n" id="mwAU8">uri</span><span class="p" id="mwAVA">);</span> <span class="w" id="mwAVE"> </span><span class="n" id="mwAVI">Task</span><span class="o" id="mwAVM"><</span><span class="kt" id="mwAVQ">int</span><span class="o" id="mwAVU">></span><span class="w" id="mwAVY"> </span><span class="n" id="mwAVc">afterDataTask</span><span class="w" id="mwAVg"> </span><span class="o" id="mwAVk">=</span><span class="w" id="mwAVo"> </span><span class="n" id="mwAVs">dataTask</span><span class="p" id="mwAVw">.</span><span class="n" id="mwAV0">ContinueWith</span><span class="p" id="mwAV4">((</span><span class="n" id="mwAV8">originalTask</span><span class="p" id="mwAWA">)</span><span class="w" id="mwAWE"> </span><span class="o" id="mwAWI">=></span><span class="w" id="mwAWM"> </span><span class="p" id="mwAWQ">{</span> <span class="w" id="mwAWU"> </span><span class="k" id="mwAWY">return</span><span class="w" id="mwAWc"> </span><span class="n" id="mwAWg">originalTask</span><span class="p" id="mwAWk">.</span><span class="n" id="mwAWo">Result</span><span class="p" id="mwAWs">.</span><span class="n" id="mwAWw">Length</span><span class="p" id="mwAW0">;</span> <span class="w" id="mwAW4"> </span><span class="p" id="mwAW8">});</span> <span class="w" id="mwAXA"> </span><span class="k" id="mwAXE">return</span><span class="w" id="mwAXI"> </span><span class="n" id="mwAXM">afterDataTask</span><span class="p" id="mwAXQ">;</span> <span class="p" id="mwAXU">}</span>Because of this, if an interface method needs to return a promise object, but itself does not require await in the body to wait on any asynchronous tasks, it does not need the async modifier either and can instead return a promise object directly. For instance, a function might be able to provide a promise that immediately resolves to some result value (such as C#'s Task.FromResult()), or it may simply return another method's promise that happens to be the exact promise needed (such as when deferring to an overload).
One important caveat of this functionality, however, is that while the code resembles traditional blocking code, the code is actually non-blocking and potentially multithreaded, meaning that many intervening events may occur while waiting for the promise targeted by an await to resolve. For instance, the following code, while always succeeding in a blocking model without await, may experience intervening events during the await and may thus find shared state changed out from under it:
<span id="mwAYY"></span><span class="k" id="mwAYc">using</span><span class="w" id="mwAYg"> </span><span class="nn" id="mwAYk">System</span><span class="p" id="mwAYo">;</span> <span class="k" id="mwAYs">using</span><span class="w" id="mwAYw"> </span><span class="nn" id="mwAY0">System.Diagnostics</span><span class="p" id="mwAY4">;</span> <span class="k" id="mwAY8">using</span><span class="w" id="mwAZA"> </span><span class="nn" id="mwAZE">System.Net.Http</span><span class="p" id="mwAZI">;</span> <span class="kt" id="mwAZM">string</span><span class="w" id="mwAZQ"> </span><span class="n" id="mwAZU">name</span><span class="w" id="mwAZY"> </span><span class="o" id="mwAZc">=</span><span class="w" id="mwAZg"> </span><span class="n" id="mwAZk">state</span><span class="p" id="mwAZo">.</span><span class="n" id="mwAZs">name</span><span class="p" id="mwAZw">;</span> <span class="n" id="mwAZ0">HttpClient</span><span class="w" id="mwAZ4"> </span><span class="n" id="mwAZ8">client</span><span class="w" id="mwAaA"> </span><span class="o" id="mwAaE">=</span><span class="w" id="mwAaI"> </span><span class="k" id="mwAaM">new</span><span class="p" id="mwAaQ">();</span> <span class="kt" id="mwAaU">byte</span><span class="p" id="mwAaY">[]</span><span class="w" id="mwAac"> </span><span class="n" id="mwAag">data</span><span class="w" id="mwAak"> </span><span class="o" id="mwAao">=</span><span class="w" id="mwAas"> </span><span class="k" id="mwAaw">await</span><span class="w" id="mwAa0"> </span><span class="n" id="mwAa4">client</span><span class="p" id="mwAa8">.</span><span class="n" id="mwAbA">GetByteArrayAsync</span><span class="p" id="mwAbE">(</span><span class="n" id="mwAbI">uri</span><span class="p" id="mwAbM">);</span> <span class="c1" id="mwAbQ">// Potential failure, as the value of state.name may have</span> <span class="c1" id="mwAbU">// been changed by the handler of an intervening event.</span> <span class="n" id="mwAbY">Debug</span><span class="p" id="mwAbc">.</span><span class="n" id="mwAbg">Assert</span><span class="p" id="mwAbk">(</span><span class="n" id="mwAbo">name</span><span class="w" id="mwAbs"> </span><span class="o" id="mwAbw">==</span><span class="w" id="mwAb0"> </span><span class="n" id="mwAb4">state</span><span class="p" id="mwAb8">.</span><span class="n" id="mwAcA">name</span><span class="p" id="mwAcE">);</span> <span class="k" id="mwAcI">return</span><span class="w" id="mwAcM"> </span><span class="n" id="mwAcQ">data</span><span class="p" id="mwAcU">.</span><span class="n" id="mwAcY">Length</span><span class="p" id="mwAcc">;</span>
Implementations
C
The C language does not support await/async. Some coroutine libraries such as s_task simulate the keywords await/async with macros.
<span id="mwAdM"></span><span class="cp" id="mwAdQ">#include</span><span class="w" id="mwAdU"> </span><span class="cpf" id="mwAdY"><stdio.h></span> <span class="cp" id="mwAdc">#include</span><span class="w" id="mwAdg"> </span><span class="cpf" id="mwAdk">"s_task.h"</span> <span class="k" id="mwAdo">constexpr</span><span class="w" id="mwAds"> </span><span class="kt" id="mwAdw">int</span><span class="w" id="mwAd0"> </span><span class="n" id="mwAd4">STACK_SIZE</span><span class="w" id="mwAd8"> </span><span class="o" id="mwAeA">=</span><span class="w" id="mwAeE"> </span><span class="mi" id="mwAeI">64</span><span class="w" id="mwAeM"> </span><span class="o" id="mwAeQ">*</span><span class="w" id="mwAeU"> </span><span class="mi" id="mwAeY">1024</span><span class="w" id="mwAec"> </span><span class="o" id="mwAeg">/</span><span class="w" id="mwAek"> </span><span class="k" id="mwAeo">sizeof</span><span class="p" id="mwAes">(</span><span class="kt" id="mwAew">int</span><span class="p" id="mwAe0">);</span> <span class="c1" id="mwAe4">// define stack memory for tasks</span> <span class="kt" id="mwAe8">int</span><span class="w" id="mwAfA"> </span><span class="n" id="mwAfE">g_stack_main</span><span class="p" id="mwAfI">[</span><span class="n" id="mwAfM">STACK_SIZE</span><span class="p" id="mwAfQ">];</span> <span class="kt" id="mwAfU">int</span><span class="w" id="mwAfY"> </span><span class="n" id="mwAfc">g_stack0</span><span class="p" id="mwAfg">[</span><span class="n" id="mwAfk">STACK_SIZE</span><span class="p" id="mwAfo">];</span> <span class="kt" id="mwAfs">int</span><span class="w" id="mwAfw"> </span><span class="n" id="mwAf0">g_stack1</span><span class="p" id="mwAf4">[</span><span class="n" id="mwAf8">STACK_SIZE</span><span class="p" id="mwAgA">];</span> <span class="kt" id="mwAgE">void</span><span class="w" id="mwAgI"> </span><span class="nf" id="mwAgM">sub_task</span><span class="p" id="mwAgQ">(</span><span class="n" id="mwAgU">__async__</span><span class="p" id="mwAgY">,</span><span class="w" id="mwAgc"> </span><span class="kt" id="mwAgg">void</span><span class="o" id="mwAgk">*</span><span class="w" id="mwAgo"> </span><span class="n" id="mwAgs">arg</span><span class="p" id="mwAgw">)</span><span class="w" id="mwAg0"> </span><span class="p" id="mwAg4">{</span> <span class="w" id="mwAg8"> </span><span class="kt" id="mwAhA">int</span><span class="w" id="mwAhE"> </span><span class="n" id="mwAhI">n</span><span class="w" id="mwAhM"> </span><span class="o" id="mwAhQ">=</span><span class="w" id="mwAhU"> </span><span class="p" id="mwAhY">(</span><span class="kt" id="mwAhc">int</span><span class="p" id="mwAhg">)(</span><span class="kt" id="mwAhk">size_t</span><span class="p" id="mwAho">)</span><span class="n" id="mwAhs">arg</span><span class="p" id="mwAhw">;</span> <span class="w" id="mwAh0"> </span><span class="k" id="mwAh4">for</span><span class="w" id="mwAh8"> </span><span class="p" id="mwAiA">(</span><span class="kt" id="mwAiE">int</span><span class="w" id="mwAiI"> </span><span class="n" id="mwAiM">i</span><span class="w" id="mwAiQ"> </span><span class="o" id="mwAiU">=</span><span class="w" id="mwAiY"> </span><span class="mi" id="mwAic">0</span><span class="p" id="mwAig">;</span><span class="w" id="mwAik"> </span><span class="n" id="mwAio">i</span><span class="w" id="mwAis"> </span><span class="o" id="mwAiw"><</span><span class="w" id="mwAi0"> </span><span class="mi" id="mwAi4">5</span><span class="p" id="mwAi8">;</span><span class="w" id="mwAjA"> </span><span class="o" id="mwAjE">++</span><span class="n" id="mwAjI">i</span><span class="p" id="mwAjM">)</span><span class="w" id="mwAjQ"> </span><span class="p" id="mwAjU">{</span> <span class="w" id="mwAjY"> </span><span class="n" id="mwAjc">printf</span><span class="p" id="mwAjg">(</span><span class="s" id="mwAjk">"task %d, delay seconds = %d, i = %d</span><span class="se" id="mwAjo">\n</span><span class="s" id="mwAjs">"</span><span class="p" id="mwAjw">,</span><span class="w" id="mwAj0"> </span><span class="n" id="mwAj4">n</span><span class="p" id="mwAj8">,</span><span class="w" id="mwAkA"> </span><span class="n" id="mwAkE">n</span><span class="p" id="mwAkI">,</span><span class="w" id="mwAkM"> </span><span class="n" id="mwAkQ">i</span><span class="p" id="mwAkU">);</span> <span class="w" id="mwAkY"> </span><span class="n" id="mwAkc">s_task_msleep</span><span class="p" id="mwAkg">(</span><span class="n" id="mwAkk">__await__</span><span class="p" id="mwAko">,</span><span class="w" id="mwAks"> </span><span class="n" id="mwAkw">n</span><span class="w" id="mwAk0"> </span><span class="o" id="mwAk4">*</span><span class="w" id="mwAk8"> </span><span class="mi" id="mwAlA">1000</span><span class="p" id="mwAlE">);</span> <span class="w" id="mwAlI"> </span><span class="c1" id="mwAlM">// s_task_yield(__await__);</span> <span class="w" id="mwAlQ"> </span><span class="p" id="mwAlU">}</span> <span class="p" id="mwAlY">}</span> <span class="kt" id="mwAlc">void</span><span class="w" id="mwAlg"> </span><span class="nf" id="mwAlk">main_task</span><span class="p" id="mwAlo">(</span><span class="n" id="mwAls">__async__</span><span class="p" id="mwAlw">,</span><span class="w" id="mwAl0"> </span><span class="kt" id="mwAl4">void</span><span class="o" id="mwAl8">*</span><span class="w" id="mwAmA"> </span><span class="n" id="mwAmE">arg</span><span class="p" id="mwAmI">)</span><span class="w" id="mwAmM"> </span><span class="p" id="mwAmQ">{</span> <span class="w" id="mwAmU"> </span><span class="c1" id="mwAmY">// create two sub-tasks</span> <span class="w" id="mwAmc"> </span><span class="n" id="mwAmg">s_task_create</span><span class="p" id="mwAmk">(</span><span class="n" id="mwAmo">g_stack0</span><span class="p" id="mwAms">,</span><span class="w" id="mwAmw"> </span><span class="k" id="mwAm0">sizeof</span><span class="p" id="mwAm4">(</span><span class="n" id="mwAm8">g_stack0</span><span class="p" id="mwAnA">),</span><span class="w" id="mwAnE"> </span><span class="n" id="mwAnI">sub_task</span><span class="p" id="mwAnM">,</span><span class="w" id="mwAnQ"> </span><span class="p" id="mwAnU">(</span><span class="kt" id="mwAnY">void</span><span class="o" id="mwAnc">*</span><span class="p" id="mwAng">)</span><span class="mi" id="mwAnk">1</span><span class="p" id="mwAno">);</span> <span class="w" id="mwAns"> </span><span class="n" id="mwAnw">s_task_create</span><span class="p" id="mwAn0">(</span><span class="n" id="mwAn4">g_stack1</span><span class="p" id="mwAn8">,</span><span class="w" id="mwAoA"> </span><span class="k" id="mwAoE">sizeof</span><span class="p" id="mwAoI">(</span><span class="n" id="mwAoM">g_stack1</span><span class="p" id="mwAoQ">),</span><span class="w" id="mwAoU"> </span><span class="n" id="mwAoY">sub_task</span><span class="p" id="mwAoc">,</span><span class="w" id="mwAog"> </span><span class="p" id="mwAok">(</span><span class="kt" id="mwAoo">void</span><span class="o" id="mwAos">*</span><span class="p" id="mwAow">)</span><span class="mi" id="mwAo0">2</span><span class="p" id="mwAo4">);</span> <span class="w" id="mwAo8"> </span><span class="k" id="mwApA">for</span><span class="w" id="mwApE"> </span><span class="p" id="mwApI">(</span><span class="kt" id="mwApM">int</span><span class="w" id="mwApQ"> </span><span class="n" id="mwApU">i</span><span class="w" id="mwApY"> </span><span class="o" id="mwApc">=</span><span class="w" id="mwApg"> </span><span class="mi" id="mwApk">0</span><span class="p" id="mwApo">;</span><span class="w" id="mwAps"> </span><span class="n" id="mwApw">i</span><span class="w" id="mwAp0"> </span><span class="o" id="mwAp4"><</span><span class="w" id="mwAp8"> </span><span class="mi" id="mwAqA">4</span><span class="p" id="mwAqE">;</span><span class="w" id="mwAqI"> </span><span class="o" id="mwAqM">++</span><span class="n" id="mwAqQ">i</span><span class="p" id="mwAqU">)</span><span class="w" id="mwAqY"> </span><span class="p" id="mwAqc">{</span> <span class="w" id="mwAqg"> </span><span class="n" id="mwAqk">printf</span><span class="p" id="mwAqo">(</span><span class="s" id="mwAqs">"task_main arg = %p, i = %d</span><span class="se" id="mwAqw">\n</span><span class="s" id="mwAq0">"</span><span class="p" id="mwAq4">,</span><span class="w" id="mwAq8"> </span><span class="n" id="mwArA">arg</span><span class="p" id="mwArE">,</span><span class="w" id="mwArI"> </span><span class="n" id="mwArM">i</span><span class="p" id="mwArQ">);</span> <span class="w" id="mwArU"> </span><span class="n" id="mwArY">s_task_yield</span><span class="p" id="mwArc">(</span><span class="n" id="mwArg">__await__</span><span class="p" id="mwArk">);</span> <span class="w" id="mwAro"> </span><span class="p" id="mwArs">}</span> <span class="w" id="mwArw"> </span><span class="c1" id="mwAr0">// wait for the sub-tasks for exit</span> <span class="w" id="mwAr4"> </span><span class="n" id="mwAr8">s_task_join</span><span class="p" id="mwAsA">(</span><span class="n" id="mwAsE">__await__</span><span class="p" id="mwAsI">,</span><span class="w" id="mwAsM"> </span><span class="n" id="mwAsQ">g_stack0</span><span class="p" id="mwAsU">);</span> <span class="w" id="mwAsY"> </span><span class="n" id="mwAsc">s_task_join</span><span class="p" id="mwAsg">(</span><span class="n" id="mwAsk">__await__</span><span class="p" id="mwAso">,</span><span class="w" id="mwAss"> </span><span class="n" id="mwAsw">g_stack1</span><span class="p" id="mwAs0">);</span> <span class="p" id="mwAs4">}</span> <span class="kt" id="mwAs8">int</span><span class="w" id="mwAtA"> </span><span class="nf" id="mwAtE">main</span><span class="p" id="mwAtI">(</span><span class="kt" id="mwAtM">int</span><span class="w" id="mwAtQ"> </span><span class="n" id="mwAtU">argc</span><span class="p" id="mwAtY">,</span><span class="w" id="mwAtc"> </span><span class="kt" id="mwAtg">char</span><span class="o" id="mwAtk">*</span><span class="w" id="mwAto"> </span><span class="n" id="mwAts">argv</span><span class="p" id="mwAtw">[])</span><span class="w" id="mwAt0"> </span><span class="p" id="mwAt4">{</span> <span class="w" id="mwAt8"> </span><span class="n" id="mwAuA">s_task_init_system</span><span class="p" id="mwAuE">();</span> <span class="w" id="mwAuI"> </span><span class="c1" id="mwAuM">// create the main task</span> <span class="w" id="mwAuQ"> </span><span class="n" id="mwAuU">s_task_create</span><span class="p" id="mwAuY">(</span><span class="n" id="mwAuc">g_stack_main</span><span class="p" id="mwAug">,</span><span class="w" id="mwAuk"> </span><span class="k" id="mwAuo">sizeof</span><span class="p" id="mwAus">(</span><span class="n" id="mwAuw">g_stack_main</span><span class="p" id="mwAu0">),</span><span class="w" id="mwAu4"> </span><span class="n" id="mwAu8">main_task</span><span class="p" id="mwAvA">,</span><span class="w" id="mwAvE"> </span><span class="p" id="mwAvI">(</span><span class="kt" id="mwAvM">void</span><span class="o" id="mwAvQ">*</span><span class="p" id="mwAvU">)(</span><span class="kt" id="mwAvY">size_t</span><span class="p" id="mwAvc">)</span><span class="n" id="mwAvg">argc</span><span class="p" id="mwAvk">);</span> <span class="w" id="mwAvo"> </span><span class="n" id="mwAvs">s_task_join</span><span class="p" id="mwAvw">(</span><span class="n" id="mwAv0">__await__</span><span class="p" id="mwAv4">,</span><span class="w" id="mwAv8"> </span><span class="n" id="mwAwA">g_stack_main</span><span class="p" id="mwAwE">);</span> <span class="w" id="mwAwI"> </span><span class="n" id="mwAwM">printf</span><span class="p" id="mwAwQ">(</span><span class="s" id="mwAwU">"all task is over</span><span class="se" id="mwAwY">\n</span><span class="s" id="mwAwc">"</span><span class="p" id="mwAwg">);</span> <span class="w" id="mwAwk"> </span><span class="k" id="mwAwo">return</span><span class="w" id="mwAws"> </span><span class="mi" id="mwAww">0</span><span class="p" id="mwAw0">;</span> <span class="p" id="mwAw4">}</span>C++
Prior to C++20, there were no equivalents to await, and C++ offered far more limited utilities for asynchronous programming. Notably, C++11 introduced std::promise<T> and std::future<T> which offered a futures and promises model, while std::async() was used to run a function asynchronously (potentially in a separate thread) and return a std::future object, specifically taking a function of type F and returning a future<invoke_result_t<decay_t<F>, decay_t<Args>...>>, as well as allowing specifying a std::launch policy.
<span id="mwAyM"></span><span class="k" id="mwAyQ">import</span><span class="w" id="mwAyU"> </span><span class="n" id="mwAyY">std</span><span class="p" id="mwAyc">;</span> <span class="k" id="mwAyg">using</span><span class="w" id="mwAyk"> </span><span class="n" id="mwAyo">std</span><span class="o" id="mwAys">::</span><span class="n" id="mwAyw">future</span><span class="p" id="mwAy0">;</span> <span class="k" id="mwAy4">using</span><span class="w" id="mwAy8"> </span><span class="n" id="mwAzA">std</span><span class="o" id="mwAzE">::</span><span class="n" id="mwAzI">launch</span><span class="p" id="mwAzM">;</span> <span class="k" id="mwAzQ">using</span><span class="w" id="mwAzU"> </span><span class="n" id="mwAzY">std</span><span class="o" id="mwAzc">::</span><span class="n" id="mwAzg">vector</span><span class="p" id="mwAzk">;</span> <span class="c1" id="mwAzo">// a heavy, CPU-bound operation</span> <span class="n" id="mwAzs">vector</span><span class="o" id="mwAzw"><</span><span class="kt" id="mwAz0">double</span><span class="o" id="mwAz4">></span><span class="w" id="mwAz8"> </span><span class="n" id="mwA0A">applyFilter</span><span class="p" id="mwA0E">(</span><span class="k" id="mwA0I">const</span><span class="w" id="mwA0M"> </span><span class="n" id="mwA0Q">vector</span><span class="o" id="mwA0U"><</span><span class="kt" id="mwA0Y">double</span><span class="o" id="mwA0c">>&</span><span class="w" id="mwA0g"> </span><span class="n" id="mwA0k">image</span><span class="p" id="mwA0o">)</span><span class="w" id="mwA0s"> </span><span class="p" id="mwA0w">{</span> <span class="w" id="mwA00"> </span><span class="c1" id="mwA04">// ...</span> <span class="p" id="mwA08">}</span> <span class="kt" id="mwA1A">int</span><span class="w" id="mwA1E"> </span><span class="n" id="mwA1I">main</span><span class="p" id="mwA1M">(</span><span class="kt" id="mwA1Q">int</span><span class="w" id="mwA1U"> </span><span class="n" id="mwA1Y">argc</span><span class="p" id="mwA1c">,</span><span class="w" id="mwA1g"> </span><span class="kt" id="mwA1k">char</span><span class="o" id="mwA1o">*</span><span class="w" id="mwA1s"> </span><span class="n" id="mwA1w">argv</span><span class="p" id="mwA10">[])</span><span class="w" id="mwA14"> </span><span class="p" id="mwA18">{</span> <span class="w" id="mwA2A"> </span><span class="c1" id="mwA2E">// a large amount of data</span> <span class="w" id="mwA2I"> </span><span class="n" id="mwA2M">vector</span><span class="o" id="mwA2Q"><</span><span class="kt" id="mwA2U">double</span><span class="o" id="mwA2Y">></span><span class="w" id="mwA2c"> </span><span class="n" id="mwA2g">imagePixels</span><span class="p" id="mwA2k">(</span><span class="mi" id="mwA2o">5'000'000</span><span class="p" id="mwA2s">);</span> <span class="w" id="mwA2w"> </span><span class="n" id="mwA20">std</span><span class="o" id="mwA24">::</span><span class="n" id="mwA28">iota</span><span class="p" id="mwA3A">(</span><span class="n" id="mwA3E">imagePixels</span><span class="p" id="mwA3I">.</span><span class="n" id="mwA3M">begin</span><span class="p" id="mwA3Q">(),</span><span class="w" id="mwA3U"> </span><span class="n" id="mwA3Y">imagePixels</span><span class="p" id="mwA3c">.</span><span class="n" id="mwA3g">end</span><span class="p" id="mwA3k">(),</span><span class="w" id="mwA3o"> </span><span class="mf" id="mwA3s">1.0</span><span class="p" id="mwA3w">);</span> <span class="w" id="mwA30"> </span><span class="n" id="mwA34">future</span><span class="o" id="mwA38"><</span><span class="n" id="mwA4A">vector</span><span class="o" id="mwA4E"><</span><span class="kt" id="mwA4I">double</span><span class="o" id="mwA4M">>></span><span class="w" id="mwA4Q"> </span><span class="n" id="mwA4U">fut</span><span class="w" id="mwA4Y"> </span><span class="o" id="mwA4c">=</span><span class="w" id="mwA4g"> </span><span class="n" id="mwA4k">std</span><span class="o" id="mwA4o">::</span><span class="n" id="mwA4s">async</span><span class="p" id="mwA4w">(</span><span class="n" id="mwA40">launch</span><span class="o" id="mwA44">::</span><span class="n" id="mwA48">async</span><span class="p" id="mwA5A">,</span><span class="w" id="mwA5E"> </span><span class="n" id="mwA5I">applyFilter</span><span class="p" id="mwA5M">,</span><span class="w" id="mwA5Q"> </span><span class="n" id="mwA5U">imagePixels</span><span class="p" id="mwA5Y">);</span> <span class="w" id="mwA5c"> </span><span class="n" id="mwA5g">vector</span><span class="o" id="mwA5k"><</span><span class="kt" id="mwA5o">double</span><span class="o" id="mwA5s">></span><span class="w" id="mwA5w"> </span><span class="n" id="mwA50">processedImage</span><span class="w" id="mwA54"> </span><span class="o" id="mwA58">=</span><span class="w" id="mwA6A"> </span><span class="n" id="mwA6E">fut</span><span class="p" id="mwA6I">.</span><span class="n" id="mwA6M">get</span><span class="p" id="mwA6Q">();</span> <span class="p" id="mwA6U">}</span>C++20 introduced a co_await (prefixed with "co" to emphasise its context in coroutines), which is an operator to suspend coroutine execution. along with co_return to terminate and return a value from the coroutine, and co_yield to suspend the coroutine and emit a value back to the caller.
A generator class std::generator<Ref, V, Alloc> was introduced in C++23, while a task class std::execution::task<T, Env> was introduced in C++26. Inside a coroutine, a task is co_awaited, but outside of coroutines, it can be called using std::this_thread::sync_wait(), which blocks and returns optional<tuple<Ts...>>.
To be co_awaitable, a type must implement a number of public member functions, such as await_ready(), await_suspend(), and await_resume() on the return type in order for the type to be awaited on. std::promise<T> and std::future<T> do not implement any of these.
<span id="mwA9M"></span><span class="k" id="mwA9Q">import</span><span class="w" id="mwA9U"> </span><span class="n" id="mwA9Y">std</span><span class="p" id="mwA9c">;</span> <span class="k" id="mwA9g">using</span><span class="w" id="mwA9k"> </span><span class="n" id="mwA9o">std</span><span class="o" id="mwA9s">::</span><span class="n" id="mwA9w">optional</span><span class="p" id="mwA90">;</span> <span class="k" id="mwA94">using</span><span class="w" id="mwA98"> </span><span class="n" id="mwA-A">std</span><span class="o" id="mwA-E">::</span><span class="n" id="mwA-I">tuple</span><span class="p" id="mwA-M">;</span> <span class="k" id="mwA-Q">using</span><span class="w" id="mwA-U"> </span><span class="n" id="mwA-Y">std</span><span class="o" id="mwA-c">::</span><span class="n" id="mwA-g">execution</span><span class="o" id="mwA-k">::</span><span class="n" id="mwA-o">task</span><span class="p" id="mwA-s">;</span> <span class="k" id="mwA-w">using</span><span class="w" id="mwA-0"> </span><span class="k" id="mwA-4">namespace</span><span class="w" id="mwA-8"> </span><span class="nn" id="mwA_A">std</span><span class="o" id="mwA_E">::</span><span class="nn" id="mwA_I">literals</span><span class="p" id="mwA_M">;</span> <span class="n" id="mwA_Q">task</span><span class="o" id="mwA_U"><</span><span class="kt" id="mwA_Y">void</span><span class="o" id="mwA_c">></span><span class="w" id="mwA_g"> </span><span class="n" id="mwA_k">simulateWork</span><span class="p" id="mwA_o">()</span><span class="w" id="mwA_s"> </span><span class="p" id="mwA_w">{</span> <span class="w" id="mwA_0"> </span><span class="n" id="mwA_4">std</span><span class="o" id="mwA_8">::</span><span class="n" id="mwBAA">println</span><span class="p" id="mwBAE">(</span><span class="s" id="mwBAI">"Performing work..."</span><span class="p" id="mwBAM">);</span> <span class="w" id="mwBAQ"> </span><span class="n" id="mwBAU">std</span><span class="o" id="mwBAY">::</span><span class="n" id="mwBAc">this_thread</span><span class="o" id="mwBAg">::</span><span class="n" id="mwBAk">sleep_for</span><span class="p" id="mwBAo">(</span><span class="mi" id="mwBAs">500</span><span class="n" id="mwBAw">ms</span><span class="p" id="mwBA0">);</span> <span class="w" id="mwBA4"> </span><span class="n" id="mwBA8">std</span><span class="o" id="mwBBA">::</span><span class="n" id="mwBBE">println</span><span class="p" id="mwBBI">(</span><span class="s" id="mwBBM">"Work done!"</span><span class="p" id="mwBBQ">);</span> <span class="w" id="mwBBU"> </span><span class="k" id="mwBBY">co_return</span><span class="p" id="mwBBc">;</span> <span class="p" id="mwBBg">}</span> <span class="n" id="mwBBk">task</span><span class="o" id="mwBBo"><</span><span class="kt" id="mwBBs">int</span><span class="o" id="mwBBw">></span><span class="w" id="mwBB0"> </span><span class="n" id="mwBB4">add</span><span class="p" id="mwBB8">(</span><span class="kt" id="mwBCA">int</span><span class="w" id="mwBCE"> </span><span class="n" id="mwBCI">a</span><span class="p" id="mwBCM">,</span><span class="w" id="mwBCQ"> </span><span class="kt" id="mwBCU">int</span><span class="w" id="mwBCY"> </span><span class="n" id="mwBCc">b</span><span class="p" id="mwBCg">)</span><span class="w" id="mwBCk"> </span><span class="k" id="mwBCo">noexcept</span><span class="w" id="mwBCs"> </span><span class="p" id="mwBCw">{</span> <span class="w" id="mwBC0"> </span><span class="k" id="mwBC4">co_await</span><span class="w" id="mwBC8"> </span><span class="n" id="mwBDA">simulateWork</span><span class="p" id="mwBDE">();</span> <span class="w" id="mwBDI"> </span><span class="k" id="mwBDM">co_return</span><span class="w" id="mwBDQ"> </span><span class="n" id="mwBDU">a</span><span class="w" id="mwBDY"> </span><span class="o" id="mwBDc">+</span><span class="w" id="mwBDg"> </span><span class="n" id="mwBDk">b</span><span class="p" id="mwBDo">;</span> <span class="p" id="mwBDs">}</span> <span class="n" id="mwBDw">task</span><span class="o" id="mwBD0"><</span><span class="kt" id="mwBD4">int</span><span class="o" id="mwBD8">></span><span class="w" id="mwBEA"> </span><span class="n" id="mwBEE">test</span><span class="p" id="mwBEI">()</span><span class="w" id="mwBEM"> </span><span class="p" id="mwBEQ">{</span> <span class="w" id="mwBEU"> </span><span class="kt" id="mwBEY">int</span><span class="w" id="mwBEc"> </span><span class="n" id="mwBEg">ret</span><span class="w" id="mwBEk"> </span><span class="o" id="mwBEo">=</span><span class="w" id="mwBEs"> </span><span class="k" id="mwBEw">co_await</span><span class="w" id="mwBE0"> </span><span class="n" id="mwBE4">add</span><span class="p" id="mwBE8">(</span><span class="mi" id="mwBFA">1</span><span class="p" id="mwBFE">,</span><span class="w" id="mwBFI"> </span><span class="mi" id="mwBFM">2</span><span class="p" id="mwBFQ">);</span> <span class="w" id="mwBFU"> </span><span class="n" id="mwBFY">std</span><span class="o" id="mwBFc">::</span><span class="n" id="mwBFg">println</span><span class="p" id="mwBFk">(</span><span class="s" id="mwBFo">"Return {}"</span><span class="p" id="mwBFs">,</span><span class="w" id="mwBFw"> </span><span class="n" id="mwBF0">ret</span><span class="p" id="mwBF4">);</span> <span class="w" id="mwBF8"> </span><span class="k" id="mwBGA">co_return</span><span class="w" id="mwBGE"> </span><span class="n" id="mwBGI">ret</span><span class="p" id="mwBGM">;</span> <span class="p" id="mwBGQ">}</span> <span class="kt" id="mwBGU">int</span><span class="w" id="mwBGY"> </span><span class="n" id="mwBGc">main</span><span class="p" id="mwBGg">(</span><span class="kt" id="mwBGk">int</span><span class="w" id="mwBGo"> </span><span class="n" id="mwBGs">argc</span><span class="p" id="mwBGw">,</span><span class="w" id="mwBG0"> </span><span class="kt" id="mwBG4">char</span><span class="o" id="mwBG8">*</span><span class="w" id="mwBHA"> </span><span class="n" id="mwBHE">argv</span><span class="p" id="mwBHI">[])</span><span class="w" id="mwBHM"> </span><span class="p" id="mwBHQ">{</span> <span class="w" id="mwBHU"> </span><span class="n" id="mwBHY">optional</span><span class="o" id="mwBHc"><</span><span class="n" id="mwBHg">tuple</span><span class="o" id="mwBHk"><</span><span class="kt" id="mwBHo">int</span><span class="o" id="mwBHs">>></span><span class="w" id="mwBHw"> </span><span class="n" id="mwBH0">result</span><span class="w" id="mwBH4"> </span><span class="o" id="mwBH8">=</span><span class="w" id="mwBIA"> </span><span class="n" id="mwBIE">std</span><span class="o" id="mwBII">::</span><span class="n" id="mwBIM">this_thread</span><span class="o" id="mwBIQ">::</span><span class="n" id="mwBIU">sync_wait</span><span class="p" id="mwBIY">(</span><span class="n" id="mwBIc">test</span><span class="p" id="mwBIg">());</span> <span class="w" id="mwBIk"> </span><span class="n" id="mwBIo">std</span><span class="o" id="mwBIs">::</span><span class="n" id="mwBIw">println</span><span class="p" id="mwBI0">(</span><span class="s" id="mwBI4">"Result: {}"</span><span class="p" id="mwBI8">,</span><span class="w" id="mwBJA"> </span><span class="n" id="mwBJE">std</span><span class="o" id="mwBJI">::</span><span class="n" id="mwBJM">get</span><span class="o" id="mwBJQ"><</span><span class="mi" id="mwBJU">0</span><span class="o" id="mwBJY">></span><span class="p" id="mwBJc">(</span><span class="n" id="mwBJg">result</span><span class="p" id="mwBJk">.</span><span class="n" id="mwBJo">value_or</span><span class="p" id="mwBJs">(</span><span class="n" id="mwBJw">std</span><span class="o" id="mwBJ0">::</span><span class="n" id="mwBJ4">make_tuple</span><span class="p" id="mwBJ8">(</span><span class="mi" id="mwBKA">-1</span><span class="p" id="mwBKE">))));</span> <span class="w" id="mwBKI"> </span><span class="c1" id="mwBKM">// assign empty tuple a sentinel identifier to check for successful completion</span> <span class="w" id="mwBKQ"> </span><span class="n" id="mwBKU">optional</span><span class="o" id="mwBKY"><</span><span class="n" id="mwBKc">tuple</span><span class="o" id="mwBKg"><>></span><span class="w" id="mwBKk"> </span><span class="n" id="mwBKo">result</span><span class="w" id="mwBKs"> </span><span class="o" id="mwBKw">=</span><span class="w" id="mwBK0"> </span><span class="n" id="mwBK4">std</span><span class="o" id="mwBK8">::</span><span class="n" id="mwBLA">this_thread</span><span class="o" id="mwBLE">::</span><span class="n" id="mwBLI">sync_wait</span><span class="p" id="mwBLM">(</span><span class="n" id="mwBLQ">simulateWork</span><span class="p" id="mwBLU">());</span> <span class="w" id="mwBLY"> </span><span class="k" id="mwBLc">if</span><span class="w" id="mwBLg"> </span><span class="p" id="mwBLk">(</span><span class="n" id="mwBLo">result</span><span class="p" id="mwBLs">.</span><span class="n" id="mwBLw">has_value</span><span class="p" id="mwBL0">())</span><span class="w" id="mwBL4"> </span><span class="p" id="mwBL8">{</span> <span class="w" id="mwBMA"> </span><span class="n" id="mwBME">std</span><span class="o" id="mwBMI">::</span><span class="n" id="mwBMM">println</span><span class="p" id="mwBMQ">(</span><span class="s" id="mwBMU">"Work completed successfully."</span><span class="p" id="mwBMY">);</span> <span class="w" id="mwBMc"> </span><span class="p" id="mwBMg">}</span><span class="w" id="mwBMk"> </span><span class="k" id="mwBMo">else</span><span class="w" id="mwBMs"> </span><span class="p" id="mwBMw">{</span> <span class="w" id="mwBM0"> </span><span class="n" id="mwBM4">std</span><span class="o" id="mwBM8">::</span><span class="n" id="mwBNA">println</span><span class="p" id="mwBNE">(</span><span class="s" id="mwBNI">"Work failed!"</span><span class="p" id="mwBNM">);</span> <span class="w" id="mwBNQ"> </span><span class="p" id="mwBNU">}</span> <span class="w" id="mwBNY"> </span><span class="k" id="mwBNc">return</span><span class="w" id="mwBNg"> </span><span class="mi" id="mwBNk">0</span><span class="p" id="mwBNo">;</span> <span class="p" id="mwBNs">}</span>C#
In 2012, C# added the async/await pattern in C# with version 5.0, which Microsoft refers to as the task-based asynchronous pattern (TAP). Async methods usually return either void, System.Threading.Tasks.Task (a "void task"), System.Threading.Tasks.Task<T>, System.Threading.Tasks.ValueTask (a "void value task") or System.Threading.Tasks.ValueTask<T>. User code can define custom types that async methods can return through custom async method builders but this is an advanced and rare scenario. Async methods that return void are intended for event handlers; in most cases where a synchronous method would return void, returning Task instead is recommended, as it allows for more intuitive exception handling (note that Task<void> is invalid in C#).
Methods that make use of await must be declared with the async keyword. In methods that have a return value of type Task<T>, methods declared with async must have a return statement of type assignable to T instead of Task<T>; the compiler wraps the value in the Task<T> generic. It is also possible to await methods that have a return type of Task or Task<T> that are declared without async.
The following async method downloads data from a URL using await. Because this method issues a task for each URI before requiring completion with the await keyword, the resources can load at the same time instead of waiting for the last resource to finish before starting to load the next.
<span id="mwBTI"></span><span class="k" id="mwBTM">namespace</span><span class="w" id="mwBTQ"> </span><span class="nn" id="mwBTU">Wikipedia.Examples</span><span class="p" id="mwBTY">;</span> <span class="k" id="mwBTc">using</span><span class="w" id="mwBTg"> </span><span class="nn" id="mwBTk">System</span><span class="p" id="mwBTo">;</span> <span class="k" id="mwBTs">using</span><span class="w" id="mwBTw"> </span><span class="nn" id="mwBT0">System.Collections.Generic</span><span class="p" id="mwBT4">;</span> <span class="k" id="mwBT8">using</span><span class="w" id="mwBUA"> </span><span class="nn" id="mwBUE">System.Net.Http</span><span class="p" id="mwBUI">;</span> <span class="k" id="mwBUM">using</span><span class="w" id="mwBUQ"> </span><span class="nn" id="mwBUU">System.Threading.Tasks</span><span class="p" id="mwBUY">;</span> <span class="k" id="mwBUc">public</span><span class="w" id="mwBUg"> </span><span class="k" id="mwBUk">class</span><span class="w" id="mwBUo"> </span><span class="nc" id="mwBUs">Example</span> <span class="p" id="mwBUw">{</span> <span class="w" id="mwBU0"> </span><span class="k" id="mwBU4">public</span><span class="w" id="mwBU8"> </span><span class="k" id="mwBVA">async</span><span class="w" id="mwBVE"> </span><span class="n" id="mwBVI">Task</span><span class="o" id="mwBVM"><</span><span class="kt" id="mwBVQ">int</span><span class="o" id="mwBVU">></span><span class="w" id="mwBVY"> </span><span class="n" id="mwBVc">SumPageSizesAsync</span><span class="p" id="mwBVg">(</span><span class="n" id="mwBVk">IEnumerable</span><span class="o" id="mwBVo"><</span><span class="n" id="mwBVs">Uri</span><span class="o" id="mwBVw">></span><span class="w" id="mwBV0"> </span><span class="n" id="mwBV4">uris</span><span class="p" id="mwBV8">)</span><span class="w" id="mwBWA"> </span> <span class="w" id="mwBWE"> </span><span class="p" id="mwBWI">{</span> <span class="w" id="mwBWM"> </span><span class="n" id="mwBWQ">HttpClient</span><span class="w" id="mwBWU"> </span><span class="n" id="mwBWY">client</span><span class="w" id="mwBWc"> </span><span class="o" id="mwBWg">=</span><span class="w" id="mwBWk"> </span><span class="k" id="mwBWo">new</span><span class="p" id="mwBWs">();</span> <span class="w" id="mwBWw"> </span><span class="kt" id="mwBW0">int</span><span class="w" id="mwBW4"> </span><span class="n" id="mwBW8">total</span><span class="w" id="mwBXA"> </span><span class="o" id="mwBXE">=</span><span class="w" id="mwBXI"> </span><span class="mi" id="mwBXM">0</span><span class="p" id="mwBXQ">;</span> <span class="w" id="mwBXU"> </span><span class="n" id="mwBXY">List</span><span class="o" id="mwBXc"><</span><span class="n" id="mwBXg">Task</span><span class="o" id="mwBXk"><</span><span class="kt" id="mwBXo">byte</span><span class="p" id="mwBXs">[]</span><span class="o" id="mwBXw">>></span><span class="w" id="mwBX0"> </span><span class="n" id="mwBX4">loadUriTasks</span><span class="w" id="mwBX8"> </span><span class="o" id="mwBYA">=</span><span class="w" id="mwBYE"> </span><span class="k" id="mwBYI">new</span><span class="p" id="mwBYM">();</span> <span class="w" id="mwBYQ"> </span><span class="k" id="mwBYU">foreach</span><span class="w" id="mwBYY"> </span><span class="p" id="mwBYc">(</span><span class="n" id="mwBYg">Uri</span><span class="w" id="mwBYk"> </span><span class="n" id="mwBYo">uri</span><span class="w" id="mwBYs"> </span><span class="k" id="mwBYw">in</span><span class="w" id="mwBY0"> </span><span class="n" id="mwBY4">uris</span><span class="p" id="mwBY8">)</span> <span class="w" id="mwBZA"> </span><span class="p" id="mwBZE">{</span> <span class="w" id="mwBZI"> </span><span class="kt" id="mwBZM">byte</span><span class="p" id="mwBZQ">[]</span><span class="w" id="mwBZU"> </span><span class="n" id="mwBZY">loadUriTask</span><span class="w" id="mwBZc"> </span><span class="o" id="mwBZg">=</span><span class="w" id="mwBZk"> </span><span class="n" id="mwBZo">client</span><span class="p" id="mwBZs">.</span><span class="n" id="mwBZw">GetByteArrayAsync</span><span class="p" id="mwBZ0">(</span><span class="n" id="mwBZ4">uri</span><span class="p" id="mwBZ8">);</span> <span class="w" id="mwBaA"> </span><span class="n" id="mwBaE">loadUriTasks</span><span class="p" id="mwBaI">.</span><span class="n" id="mwBaM">Add</span><span class="p" id="mwBaQ">(</span><span class="n" id="mwBaU">loadUriTask</span><span class="p" id="mwBaY">);</span> <span class="w" id="mwBac"> </span><span class="p" id="mwBag">}</span> <span class="w" id="mwBak"> </span><span class="k" id="mwBao">foreach</span><span class="w" id="mwBas"> </span><span class="p" id="mwBaw">(</span><span class="n" id="mwBa0">Task</span><span class="o" id="mwBa4"><</span><span class="kt" id="mwBa8">byte</span><span class="p" id="mwBbA">[]</span><span class="o" id="mwBbE">>></span><span class="w" id="mwBbI"> </span><span class="n" id="mwBbM">loadUriTask</span><span class="w" id="mwBbQ"> </span><span class="k" id="mwBbU">in</span><span class="w" id="mwBbY"> </span><span class="n" id="mwBbc">loadUriTasks</span><span class="p" id="mwBbg">)</span> <span class="w" id="mwBbk"> </span><span class="p" id="mwBbo">{</span> <span class="w" id="mwBbs"> </span><span class="n" id="mwBbw">statusText</span><span class="p" id="mwBb0">.</span><span class="n" id="mwBb4">Text</span><span class="w" id="mwBb8"> </span><span class="o" id="mwBcA">=</span><span class="w" id="mwBcE"> </span><span class="s" id="mwBcI">$"Found {total} bytes ..."</span><span class="p" id="mwBcM">;</span> <span class="w" id="mwBcQ"> </span><span class="kt" id="mwBcU">byte</span><span class="p" id="mwBcY">[]</span><span class="w" id="mwBcc"> </span><span class="n" id="mwBcg">resourceAsBytes</span><span class="w" id="mwBck"> </span><span class="o" id="mwBco">=</span><span class="w" id="mwBcs"> </span><span class="k" id="mwBcw">await</span><span class="w" id="mwBc0"> </span><span class="n" id="mwBc4">loadUriTask</span><span class="p" id="mwBc8">;</span> <span class="w" id="mwBdA"> </span><span class="n" id="mwBdE">total</span><span class="w" id="mwBdI"> </span><span class="o" id="mwBdM">+=</span><span class="w" id="mwBdQ"> </span><span class="n" id="mwBdU">resourceAsBytes</span><span class="p" id="mwBdY">.</span><span class="n" id="mwBdc">Length</span><span class="p" id="mwBdg">;</span> <span class="w" id="mwBdk"> </span><span class="p" id="mwBdo">}</span> <span class="w" id="mwBds"> </span><span class="n" id="mwBdw">statusText</span><span class="p" id="mwBd0">.</span><span class="n" id="mwBd4">Text</span><span class="w" id="mwBd8"> </span><span class="o" id="mwBeA">=</span><span class="w" id="mwBeE"> </span><span class="s" id="mwBeI">$"Found {total} bytes total"</span><span class="p" id="mwBeM">;</span> <span class="w" id="mwBeQ"> </span><span class="k" id="mwBeU">return</span><span class="w" id="mwBeY"> </span><span class="n" id="mwBec">total</span><span class="p" id="mwBeg">;</span> <span class="w" id="mwBek"> </span><span class="p" id="mwBeo">}</span> <span class="w" id="mwBes"> </span><span class="k" id="mwBew">static</span><span class="w" id="mwBe0"> </span><span class="k" id="mwBe4">async</span><span class="w" id="mwBe8"> </span><span class="n" id="mwBfA">Task</span><span class="w" id="mwBfE"> </span><span class="nf" id="mwBfI">Main</span><span class="p" id="mwBfM">(</span><span class="kt" id="mwBfQ">string</span><span class="p" id="mwBfU">[]</span><span class="w" id="mwBfY"> </span><span class="n" id="mwBfc">args</span><span class="p" id="mwBfg">)</span> <span class="w" id="mwBfk"> </span><span class="p" id="mwBfo">{</span> <span class="w" id="mwBfs"> </span><span class="n" id="mwBfw">List</span><span class="o" id="mwBf0"><</span><span class="n" id="mwBf4">Uri</span><span class="o" id="mwBf8">></span><span class="w" id="mwBgA"> </span><span class="n" id="mwBgE">uris</span><span class="w" id="mwBgI"> </span><span class="o" id="mwBgM">=</span><span class="w" id="mwBgQ"> </span><span class="k" id="mwBgU">new</span> <span class="w" id="mwBgY"> </span><span class="p" id="mwBgc">{</span> <span class="w" id="mwBgg"> </span><span class="k" id="mwBgk">new</span><span class="w" id="mwBgo"> </span><span class="nf" id="mwBgs">Uri</span><span class="p" id="mwBgw">(</span><span class="s" id="mwBg0">"https://en.wikipedia.org"</span><span class="p" id="mwBg4">),</span> <span class="w" id="mwBg8"> </span><span class="k" id="mwBhA">new</span><span class="w" id="mwBhE"> </span><span class="nf" id="mwBhI">Uri</span><span class="p" id="mwBhM">(</span><span class="s" id="mwBhQ">"https://www.microsoft.com"</span><span class="p" id="mwBhU">),</span> <span class="w" id="mwBhY"> </span><span class="k" id="mwBhc">new</span><span class="w" id="mwBhg"> </span><span class="nf" id="mwBhk">Uri</span><span class="p" id="mwBho">(</span><span class="s" id="mwBhs">"https://www.github.com"</span><span class="p" id="mwBhw">)</span> <span class="w" id="mwBh0"> </span><span class="p" id="mwBh4">}</span> <span class="w" id="mwBh8"> </span><span class="kt" id="mwBiA">int</span><span class="w" id="mwBiE"> </span><span class="n" id="mwBiI">totalBytes</span><span class="w" id="mwBiM"> </span><span class="o" id="mwBiQ">=</span><span class="w" id="mwBiU"> </span><span class="k" id="mwBiY">await</span><span class="w" id="mwBic"> </span><span class="n" id="mwBig">SumPageSizesAsync</span><span class="p" id="mwBik">(</span><span class="n" id="mwBio">uris</span><span class="p" id="mwBis">);</span> <span class="w" id="mwBiw"> </span><span class="n" id="mwBi0">Console</span><span class="p" id="mwBi4">.</span><span class="n" id="mwBi8">WriteLine</span><span class="p" id="mwBjA">(</span><span class="s" id="mwBjE">$"Total bytes downloaded: {totalbytes}"</span><span class="p" id="mwBjI">);</span> <span class="w" id="mwBjM"> </span><span class="p" id="mwBjQ">}</span> <span class="p" id="mwBjU">}</span>F#
In 2007, F# added asynchronous workflows with version 2.0. The asynchronous workflows are implemented as CE (computation expressions). They can be defined without specifying any special context (like async in C#). F# asynchronous workflows append a bang (!) to keywords to start asynchronous tasks.
The following async function downloads data from an URL using an asynchronous workflow:
<span id="mwBkQ"></span><span class="k" id="mwBkU">let</span><span class="w" id="mwBkY"> </span><span class="nv" id="mwBkc">asyncSumPageSizes</span><span class="w" id="mwBkg"> </span><span class="o" id="mwBkk">(</span><span class="n" id="mwBko">uris</span><span class="o" id="mwBks">:</span><span class="w" id="mwBkw"> </span><span class="o" id="mwBk0">#</span><span class="n" id="mwBk4">seq</span><span class="o" id="mwBk8"><</span><span class="n" id="mwBlA">Uri</span><span class="o" id="mwBlE">>)</span><span class="w" id="mwBlI"> </span><span class="o" id="mwBlM">:</span><span class="w" id="mwBlQ"> </span><span class="n" id="mwBlU">Async</span><span class="o" id="mwBlY"><</span><span class="n" id="mwBlc">int</span><span class="o" id="mwBlg">></span><span class="w" id="mwBlk"> </span><span class="o" id="mwBlo">=</span><span class="w" id="mwBls"> </span><span class="n" id="mwBlw">async</span><span class="w" id="mwBl0"> </span><span class="o" id="mwBl4">{</span> <span class="w" id="mwBl8"> </span><span class="k" id="mwBmA">use</span><span class="w" id="mwBmE"> </span><span class="n" id="mwBmI">httpClient</span><span class="w" id="mwBmM"> </span><span class="o" id="mwBmQ">=</span><span class="w" id="mwBmU"> </span><span class="k" id="mwBmY">new</span><span class="w" id="mwBmc"> </span><span class="n" id="mwBmg">HttpClient</span><span class="bp" id="mwBmk">()</span> <span class="w" id="mwBmo"> </span><span class="k" id="mwBms">let!</span><span class="w" id="mwBmw"> </span><span class="nv" id="mwBm0">pages</span><span class="w" id="mwBm4"> </span><span class="o" id="mwBm8">=</span><span class="w" id="mwBnA"> </span> <span class="w" id="mwBnE"> </span><span class="n" id="mwBnI">uris</span> <span class="w" id="mwBnM"> </span><span class="o" id="mwBnQ">|></span><span class="w" id="mwBnU"> </span><span class="nn" id="mwBnY">Seq</span><span class="p" id="mwBnc">.</span><span class="n" id="mwBng">map</span><span class="o" id="mwBnk">(</span><span class="n" id="mwBno">httpClient</span><span class="o" id="mwBns">.</span><span class="n" id="mwBnw">GetStringAsync</span><span class="w" id="mwBn0"> </span><span class="o" id="mwBn4">>></span><span class="w" id="mwBn8"> </span><span class="nn" id="mwBoA">Async</span><span class="p" id="mwBoE">.</span><span class="n" id="mwBoI">AwaitTask</span><span class="o" id="mwBoM">)</span> <span class="w" id="mwBoQ"> </span><span class="o" id="mwBoU">|></span><span class="w" id="mwBoY"> </span><span class="nn" id="mwBoc">Async</span><span class="p" id="mwBog">.</span><span class="n" id="mwBok">Parallel</span> <span class="w" id="mwBoo"> </span><span class="k" id="mwBos">return</span><span class="w" id="mwBow"> </span><span class="n" id="mwBo0">pages</span><span class="w" id="mwBo4"> </span><span class="o" id="mwBo8">|></span><span class="w" id="mwBpA"> </span><span class="nn" id="mwBpE">Seq</span><span class="p" id="mwBpI">.</span><span class="n" id="mwBpM">fold</span><span class="w" id="mwBpQ"> </span><span class="o" id="mwBpU">(</span><span class="k" id="mwBpY">fun</span><span class="w" id="mwBpc"> </span><span class="n" id="mwBpg">accumulator</span><span class="w" id="mwBpk"> </span><span class="n" id="mwBpo">current</span><span class="w" id="mwBps"> </span><span class="o" id="mwBpw">-></span><span class="w" id="mwBp0"> </span><span class="n" id="mwBp4">current</span><span class="o" id="mwBp8">.</span><span class="n" id="mwBqA">Length</span><span class="w" id="mwBqE"> </span><span class="o" id="mwBqI">+</span><span class="w" id="mwBqM"> </span><span class="n" id="mwBqQ">accumulator</span><span class="o" id="mwBqU">)</span><span class="w" id="mwBqY"> </span><span class="mi" id="mwBqc">0</span> <span class="o" id="mwBqg">}</span>Java
Java does not have async and await keywords in the language, however it can be emulated using the java.util.concurrent package, such as the class java.util.concurrent.CompletableFuture<T> (introduced in Java 8). Asynchronous programming is later improved in Java 21 with the introduction of virtual threads and structured task scopes.
<span id="mwBrM"></span><span class="kn" id="mwBrQ">package</span><span class="w" id="mwBrU"> </span><span class="nn" id="mwBrY">org.wikipedia.examples</span><span class="p" id="mwBrc">;</span> <span class="kn" id="mwBrg">import</span><span class="w" id="mwBrk"> </span><span class="nn" id="mwBro">java.util.concurrent.CompletableFuture</span><span class="p" id="mwBrs">;</span> <span class="kn" id="mwBrw">import</span><span class="w" id="mwBr0"> </span><span class="nn" id="mwBr4">java.util.concurrent.ExecutionException</span><span class="p" id="mwBr8">;</span> <span class="kn" id="mwBsA">import</span><span class="w" id="mwBsE"> </span><span class="nn" id="mwBsI">java.util.concurrent.ExecutorService</span><span class="p" id="mwBsM">;</span> <span class="kn" id="mwBsQ">import</span><span class="w" id="mwBsU"> </span><span class="nn" id="mwBsY">java.util.concurrent.Executors</span><span class="p" id="mwBsc">;</span> <span class="kn" id="mwBsg">import</span><span class="w" id="mwBsk"> </span><span class="nn" id="mwBso">java.util.concurrent.Future</span><span class="p" id="mwBss">;</span> <span class="kn" id="mwBsw">import</span><span class="w" id="mwBs0"> </span><span class="nn" id="mwBs4">java.util.concurrent.StructuredTaskScope</span><span class="p" id="mwBs8">;</span> <span class="kd" id="mwBtA">public</span><span class="w" id="mwBtE"> </span><span class="kd" id="mwBtI">class</span> <span class="nc" id="mwBtM">AsyncExample</span><span class="w" id="mwBtQ"> </span><span class="p" id="mwBtU">{</span> <span class="w" id="mwBtY"> </span><span class="kd" id="mwBtc">public</span><span class="w" id="mwBtg"> </span><span class="n" id="mwBtk">String</span><span class="w" id="mwBto"> </span><span class="nf" id="mwBts">fetchData</span><span class="p" id="mwBtw">()</span><span class="w" id="mwBt0"> </span><span class="p" id="mwBt4">{</span> <span class="w" id="mwBt8"> </span><span class="c1" id="mwBuA">// Simulate a time-consuming operation (e.g., network request, database query)</span> <span class="w" id="mwBuE"> </span><span class="k" id="mwBuI">try</span><span class="w" id="mwBuM"> </span><span class="p" id="mwBuQ">{</span> <span class="w" id="mwBuU"> </span><span class="n" id="mwBuY">Thread</span><span class="p" id="mwBuc">.</span><span class="na" id="mwBug">sleep</span><span class="p" id="mwBuk">(</span><span class="mi" id="mwBuo">2000</span><span class="p" id="mwBus">);</span> <span class="w" id="mwBuw"> </span><span class="p" id="mwBu0">}</span><span class="w" id="mwBu4"> </span><span class="k" id="mwBu8">catch</span><span class="w" id="mwBvA"> </span><span class="p" id="mwBvE">(</span><span class="n" id="mwBvI">InterruptedException</span><span class="w" id="mwBvM"> </span><span class="n" id="mwBvQ">e</span><span class="p" id="mwBvU">)</span><span class="w" id="mwBvY"> </span><span class="p" id="mwBvc">{</span> <span class="w" id="mwBvg"> </span><span class="n" id="mwBvk">Thread</span><span class="p" id="mwBvo">.</span><span class="na" id="mwBvs">currentThread</span><span class="p" id="mwBvw">().</span><span class="na" id="mwBv0">interrupt</span><span class="p" id="mwBv4">();</span> <span class="w" id="mwBv8"> </span><span class="p" id="mwBwA">}</span> <span class="w" id="mwBwE"> </span><span class="k" id="mwBwI">return</span><span class="w" id="mwBwM"> </span><span class="s" id="mwBwQ">"Data from remote source"</span><span class="p" id="mwBwU">;</span> <span class="w" id="mwBwY"> </span><span class="p" id="mwBwc">}</span> <span class="w" id="mwBwg"> </span><span class="kd" id="mwBwk">public</span><span class="w" id="mwBwo"> </span><span class="n" id="mwBws">CompletableFuture</span><span class="o" id="mwBww"><</span><span class="n" id="mwBw0">String</span><span class="o" id="mwBw4">></span><span class="w" id="mwBw8"> </span><span class="nf" id="mwBxA">fetchDataAsync</span><span class="p" id="mwBxE">()</span><span class="w" id="mwBxI"> </span><span class="p" id="mwBxM">{</span> <span class="w" id="mwBxQ"> </span><span class="k" id="mwBxU">return</span><span class="w" id="mwBxY"> </span><span class="n" id="mwBxc">CompletableFuture</span><span class="p" id="mwBxg">.</span><span class="na" id="mwBxk">supplyAsync</span><span class="p" id="mwBxo">(()</span><span class="w" id="mwBxs"> </span><span class="o" id="mwBxw">-></span><span class="w" id="mwBx0"> </span><span class="n" id="mwBx4">fetchData</span><span class="p" id="mwBx8">());</span> <span class="w" id="mwByA"> </span><span class="p" id="mwByE">}</span> <span class="w" id="mwByI"> </span><span class="kd" id="mwByM">public</span><span class="w" id="mwByQ"> </span><span class="kd" id="mwByU">static</span><span class="w" id="mwByY"> </span><span class="kt" id="mwByc">void</span><span class="w" id="mwByg"> </span><span class="nf" id="mwByk">main</span><span class="p" id="mwByo">(</span><span class="n" id="mwBys">String</span><span class="o" id="mwByw">[]</span><span class="w" id="mwBy0"> </span><span class="n" id="mwBy4">args</span><span class="p" id="mwBy8">)</span><span class="w" id="mwBzA"> </span><span class="kd" id="mwBzE">throws</span><span class="w" id="mwBzI"> </span><span class="n" id="mwBzM">ExecutionException</span><span class="p" id="mwBzQ">,</span><span class="w" id="mwBzU"> </span><span class="n" id="mwBzY">InterruptedException</span><span class="w" id="mwBzc"> </span><span class="p" id="mwBzg">{</span> <span class="w" id="mwBzk"> </span><span class="n" id="mwBzo">AsyncExample</span><span class="w" id="mwBzs"> </span><span class="n" id="mwBzw">example</span><span class="w" id="mwBz0"> </span><span class="o" id="mwBz4">=</span><span class="w" id="mwBz8"> </span><span class="k" id="mwB0A">new</span><span class="w" id="mwB0E"> </span><span class="n" id="mwB0I">AsyncExample</span><span class="p" id="mwB0M">();</span> <span class="w" id="mwB0Q"> </span><span class="c1" id="mwB0U">// Using CompletableFuture (Java 8)</span> <span class="w" id="mwB0Y"> </span><span class="n" id="mwB0c">System</span><span class="p" id="mwB0g">.</span><span class="na" id="mwB0k">out</span><span class="p" id="mwB0o">.</span><span class="na" id="mwB0s">println</span><span class="p" id="mwB0w">(</span><span class="s" id="mwB00">"Starting asynchronous operation..."</span><span class="p" id="mwB04">);</span> <span class="w" id="mwB08"> </span><span class="n" id="mwB1A">CompletableFuture</span><span class="o" id="mwB1E"><</span><span class="n" id="mwB1I">String</span><span class="o" id="mwB1M">></span><span class="w" id="mwB1Q"> </span><span class="n" id="mwB1U">future</span><span class="w" id="mwB1Y"> </span><span class="o" id="mwB1c">=</span><span class="w" id="mwB1g"> </span><span class="n" id="mwB1k">example</span><span class="p" id="mwB1o">.</span><span class="na" id="mwB1s">fetchDataAsync</span><span class="p" id="mwB1w">();</span> <span class="w" id="mwB10"> </span><span class="n" id="mwB14">System</span><span class="p" id="mwB18">.</span><span class="na" id="mwB2A">out</span><span class="p" id="mwB2E">.</span><span class="na" id="mwB2I">println</span><span class="p" id="mwB2M">(</span><span class="s" id="mwB2Q">"Doing other work..."</span><span class="p" id="mwB2U">);</span> <span class="w" id="mwB2Y"> </span><span class="c1" id="mwB2c">// Wait for the result (similar to 'await')</span> <span class="w" id="mwB2g"> </span><span class="n" id="mwB2k">String</span><span class="w" id="mwB2o"> </span><span class="n" id="mwB2s">result</span><span class="w" id="mwB2w"> </span><span class="o" id="mwB20">=</span><span class="w" id="mwB24"> </span><span class="n" id="mwB28">future</span><span class="p" id="mwB3A">.</span><span class="na" id="mwB3E">get</span><span class="p" id="mwB3I">();</span><span class="w" id="mwB3M"> </span> <span class="w" id="mwB3Q"> </span><span class="n" id="mwB3U">System</span><span class="p" id="mwB3Y">.</span><span class="na" id="mwB3c">out</span><span class="p" id="mwB3g">.</span><span class="na" id="mwB3k">printf</span><span class="p" id="mwB3o">(</span><span class="s" id="mwB3s">"Received result: %s%n"</span><span class="p" id="mwB3w">,</span><span class="w" id="mwB30"> </span><span class="n" id="mwB34">result</span><span class="p" id="mwB38">);</span> <span class="w" id="mwB4A"> </span><span class="c1" id="mwB4E">// Using Virtual Threads (Java 21):</span> <span class="w" id="mwB4I"> </span><span class="n" id="mwB4M">ExecutorService</span><span class="w" id="mwB4Q"> </span><span class="n" id="mwB4U">extor</span><span class="w" id="mwB4Y"> </span><span class="o" id="mwB4c">=</span><span class="w" id="mwB4g"> </span><span class="n" id="mwB4k">Executors</span><span class="p" id="mwB4o">.</span><span class="na" id="mwB4s">newVirtualThreadPerTaskExecutor</span><span class="p" id="mwB4w">();</span> <span class="w" id="mwB40"> </span><span class="n" id="mwB44">System</span><span class="p" id="mwB48">.</span><span class="na" id="mwB5A">out</span><span class="p" id="mwB5E">.</span><span class="na" id="mwB5I">println</span><span class="p" id="mwB5M">(</span><span class="s" id="mwB5Q">"Starting virtual thread operation..."</span><span class="p" id="mwB5U">);</span> <span class="w" id="mwB5Y"> </span><span class="n" id="mwB5c">Future</span><span class="o" id="mwB5g"><</span><span class="n" id="mwB5k">String</span><span class="o" id="mwB5o">></span><span class="w" id="mwB5s"> </span><span class="n" id="mwB5w">fut</span><span class="w" id="mwB50"> </span><span class="o" id="mwB54">=</span><span class="w" id="mwB58"> </span><span class="n" id="mwB6A">extor</span><span class="p" id="mwB6E">.</span><span class="na" id="mwB6I">submit</span><span class="p" id="mwB6M">(()</span><span class="w" id="mwB6Q"> </span><span class="o" id="mwB6U">-></span><span class="w" id="mwB6Y"> </span><span class="p" id="mwB6c">{</span> <span class="w" id="mwB6g"> </span><span class="k" id="mwB6k">return</span><span class="w" id="mwB6o"> </span><span class="n" id="mwB6s">example</span><span class="p" id="mwB6w">.</span><span class="na" id="mwB60">fetchData</span><span class="p" id="mwB64">();</span> <span class="w" id="mwB68"> </span><span class="p" id="mwB7A">});</span> <span class="w" id="mwB7E"> </span><span class="n" id="mwB7I">System</span><span class="p" id="mwB7M">.</span><span class="na" id="mwB7Q">out</span><span class="p" id="mwB7U">.</span><span class="na" id="mwB7Y">println</span><span class="p" id="mwB7c">(</span><span class="s" id="mwB7g">"Doing other work..."</span><span class="p" id="mwB7k">);</span> <span class="w" id="mwB7o"> </span><span class="n" id="mwB7s">String</span><span class="w" id="mwB7w"> </span><span class="n" id="mwB70">result</span><span class="w" id="mwB74"> </span><span class="o" id="mwB78">=</span><span class="w" id="mwB8A"> </span><span class="n" id="mwB8E">future</span><span class="p" id="mwB8I">.</span><span class="na" id="mwB8M">get</span><span class="p" id="mwB8Q">();</span><span class="w" id="mwB8U"> </span> <span class="w" id="mwB8Y"> </span><span class="n" id="mwB8c">System</span><span class="p" id="mwB8g">.</span><span class="na" id="mwB8k">out</span><span class="p" id="mwB8o">.</span><span class="na" id="mwB8s">printf</span><span class="p" id="mwB8w">(</span><span class="s" id="mwB80">"Received result: %s%n"</span><span class="p" id="mwB84">,</span><span class="w" id="mwB88"> </span><span class="n" id="mwB9A">result</span><span class="p" id="mwB9E">);</span> <span class="w" id="mwB9I"> </span><span class="n" id="mwB9M">extor</span><span class="p" id="mwB9Q">.</span><span class="na" id="mwB9U">shutdown</span><span class="p" id="mwB9Y">();</span> <span class="w" id="mwB9c"> </span><span class="c1" id="mwB9g">// Using StructuredTaskScope (Java 21)</span> <span class="w" id="mwB9k"> </span><span class="k" id="mwB9o">try</span><span class="w" id="mwB9s"> </span><span class="p" id="mwB9w">(</span><span class="n" id="mwB90">StructuredTaskScope</span><span class="p" id="mwB94">.</span><span class="na" id="mwB98">ShutdownOnFailure</span><span class="w" id="mwB-A"> </span><span class="n" id="mwB-E">scope</span><span class="w" id="mwB-I"> </span><span class="o" id="mwB-M">=</span><span class="w" id="mwB-Q"> </span><span class="k" id="mwB-U">new</span><span class="w" id="mwB-Y"> </span><span class="n" id="mwB-c">StructuredTaskScope</span><span class="p" id="mwB-g">.</span><span class="na" id="mwB-k">ShutdownOnFailure</span><span class="p" id="mwB-o">())</span><span class="w" id="mwB-s"> </span><span class="p" id="mwB-w">{</span> <span class="w" id="mwB-0"> </span><span class="n" id="mwB-4">StructuredTaskScope</span><span class="p" id="mwB-8">.</span><span class="na" id="mwB_A">Subtask</span><span class="o" id="mwB_E"><</span><span class="n" id="mwB_I">String</span><span class="o" id="mwB_M">></span><span class="w" id="mwB_Q"> </span><span class="n" id="mwB_U">dataTask</span><span class="w" id="mwB_Y"> </span><span class="o" id="mwB_c">=</span><span class="w" id="mwB_g"> </span><span class="n" id="mwB_k">scope</span><span class="p" id="mwB_o">.</span><span class="na" id="mwB_s">fork</span><span class="p" id="mwB_w">(</span><span class="n" id="mwB_0">example</span><span class="p" id="mwB_4">::</span><span class="n" id="mwB_8">fetchData</span><span class="p" id="mwCAA">);</span> <span class="w" id="mwCAE"> </span> <span class="w" id="mwCAI"> </span><span class="n" id="mwCAM">System</span><span class="p" id="mwCAQ">.</span><span class="na" id="mwCAU">out</span><span class="p" id="mwCAY">.</span><span class="na" id="mwCAc">println</span><span class="p" id="mwCAg">(</span><span class="s" id="mwCAk">"Doing other work..."</span><span class="p" id="mwCAo">);</span> <span class="w" id="mwCAs"> </span><span class="n" id="mwCAw">scope</span><span class="p" id="mwCA0">.</span><span class="na" id="mwCA4">join</span><span class="p" id="mwCA8">();</span><span class="w" id="mwCBA"> </span><span class="c1" id="mwCBE">// wait for all tasks</span> <span class="w" id="mwCBI"> </span><span class="n" id="mwCBM">scope</span><span class="p" id="mwCBQ">.</span><span class="na" id="mwCBU">throwIfFailed</span><span class="p" id="mwCBY">();</span><span class="w" id="mwCBc"> </span><span class="c1" id="mwCBg">// propagate if any exceptions</span> <span class="w" id="mwCBk"> </span><span class="n" id="mwCBo">String</span><span class="w" id="mwCBs"> </span><span class="n" id="mwCBw">result</span><span class="w" id="mwCB0"> </span><span class="o" id="mwCB4">=</span><span class="w" id="mwCB8"> </span><span class="n" id="mwCCA">future</span><span class="p" id="mwCCE">.</span><span class="na" id="mwCCI">get</span><span class="p" id="mwCCM">();</span><span class="w" id="mwCCQ"> </span> <span class="w" id="mwCCU"> </span><span class="n" id="mwCCY">System</span><span class="p" id="mwCCc">.</span><span class="na" id="mwCCg">out</span><span class="p" id="mwCCk">.</span><span class="na" id="mwCCo">printf</span><span class="p" id="mwCCs">(</span><span class="s" id="mwCCw">"Received result: %s%n"</span><span class="p" id="mwCC0">,</span><span class="w" id="mwCC4"> </span><span class="n" id="mwCC8">result</span><span class="p" id="mwCDA">);</span> <span class="w" id="mwCDE"> </span><span class="p" id="mwCDI">}</span> <span class="w" id="mwCDM"> </span><span class="p" id="mwCDQ">}</span> <span class="p" id="mwCDU">}</span>JavaScript
The await operator in JavaScript (and TypeScript) can only be used from inside an async function or at the top level of a module. If the parameter is a promise, execution of the async function will resume when the promise is resolved (unless the promise is rejected, in which case an error will be thrown that can be handled with normal JavaScript exception handling). If the parameter is a thenable object, a new promise will be constructed with the native Promise constructor by calling the object's then() method and passing in a handler that calls the resolve callback. Otherwise, the parameter itself will be returned immediately.
Many libraries provide promise objects that can also be used with await, as long as they match the specification for native JavaScript promises. However, promises from the jQuery library were not Promises/A+ compatible until jQuery 3.0.
Below is an example (modified from this article):
<span id="mwCFQ"></span><span class="kd" id="mwCFU">interface</span><span class="w" id="mwCFY"> </span><span class="nx" id="mwCFc">DBResponse</span><span class="w" id="mwCFg"> </span><span class="p" id="mwCFk">{</span> <span class="w" id="mwCFo"> </span><span class="nx" id="mwCFs">id</span><span class="o" id="mwCFw">:</span><span class="w" id="mwCF0"> </span><span class="kt" id="mwCF4">string</span><span class="p" id="mwCF8">;</span> <span class="w" id="mwCGA"> </span><span class="nx" id="mwCGE">rev?</span><span class="o" id="mwCGI">:</span><span class="w" id="mwCGM"> </span><span class="kt" id="mwCGQ">string</span><span class="p" id="mwCGU">;</span> <span class="w" id="mwCGY"> </span><span class="nx" id="mwCGc">ok?</span><span class="o" id="mwCGg">:</span><span class="w" id="mwCGk"> </span><span class="kt" id="mwCGo">boolean</span><span class="p" id="mwCGs">;</span> <span class="p" id="mwCGw">}</span> <span class="kd" id="mwCG0">interface</span><span class="w" id="mwCG4"> </span><span class="nx" id="mwCG8">Document</span><span class="w" id="mwCHA"> </span><span class="p" id="mwCHE">{</span> <span class="w" id="mwCHI"> </span><span class="nx" id="mwCHM">_id</span><span class="o" id="mwCHQ">:</span><span class="w" id="mwCHU"> </span><span class="kt" id="mwCHY">string</span><span class="p" id="mwCHc">;</span> <span class="w" id="mwCHg"> </span><span class="nx" id="mwCHk">_rev?</span><span class="o" id="mwCHo">:</span><span class="w" id="mwCHs"> </span><span class="kt" id="mwCHw">string</span><span class="p" id="mwCH0">;</span> <span class="w" id="mwCH4"> </span><span class="p" id="mwCH8">[</span><span class="nx" id="mwCIA">key</span><span class="o" id="mwCIE">:</span><span class="w" id="mwCII"> </span><span class="kt" id="mwCIM">string</span><span class="p" id="mwCIQ">]</span><span class="o" id="mwCIU">:</span><span class="w" id="mwCIY"> </span><span class="nx" id="mwCIc">any</span><span class="p" id="mwCIg">;</span> <span class="p" id="mwCIk">}</span> <span class="kd" id="mwCIo">interface</span><span class="w" id="mwCIs"> </span><span class="nx" id="mwCIw">Database</span><span class="w" id="mwCI0"> </span><span class="p" id="mwCI4">{</span> <span class="w" id="mwCI8"> </span><span class="nx" id="mwCJA">post</span><span class="p" id="mwCJE">(</span><span class="nx" id="mwCJI">doc</span><span class="o" id="mwCJM">:</span><span class="w" id="mwCJQ"> </span><span class="kt" id="mwCJU">object</span><span class="p" id="mwCJY">)</span><span class="o" id="mwCJc">:</span><span class="w" id="mwCJg"> </span><span class="nb" id="mwCJk">Promise</span><span class="o" id="mwCJo"><</span><span class="nx" id="mwCJs">DBResponse</span><span class="o" id="mwCJw">></span><span class="p" id="mwCJ0">;</span> <span class="w" id="mwCJ4"> </span><span class="nx" id="mwCJ8">get</span><span class="p" id="mwCKA">(</span><span class="nx" id="mwCKE">id</span><span class="o" id="mwCKI">:</span><span class="w" id="mwCKM"> </span><span class="kt" id="mwCKQ">string</span><span class="p" id="mwCKU">)</span><span class="o" id="mwCKY">:</span><span class="w" id="mwCKc"> </span><span class="nb" id="mwCKg">Promise</span><span class="o" id="mwCKk"><</span><span class="nx" id="mwCKo">Document</span><span class="o" id="mwCKs">></span><span class="p" id="mwCKw">;</span> <span class="p" id="mwCK0">}</span> <span class="kr" id="mwCK4">declare</span><span class="w" id="mwCK8"> </span><span class="kd" id="mwCLA">const</span><span class="w" id="mwCLE"> </span><span class="nx" id="mwCLI">db</span><span class="o" id="mwCLM">:</span><span class="w" id="mwCLQ"> </span><span class="kt" id="mwCLU">Database</span><span class="p" id="mwCLY">;</span> <span class="k" id="mwCLc">async</span><span class="w" id="mwCLg"> </span><span class="kd" id="mwCLk">function</span><span class="w" id="mwCLo"> </span><span class="nx" id="mwCLs">createNewDoc</span><span class="p" id="mwCLw">()</span><span class="o" id="mwCL0">:</span><span class="w" id="mwCL4"> </span><span class="nb" id="mwCL8">Promise</span><span class="o" id="mwCMA"><</span><span class="nx" id="mwCME">Document</span><span class="o" id="mwCMI">></span><span class="w" id="mwCMM"> </span><span class="p" id="mwCMQ">{</span> <span class="w" id="mwCMU"> </span><span class="kd" id="mwCMY">const</span><span class="w" id="mwCMc"> </span><span class="nx" id="mwCMg">response</span><span class="o" id="mwCMk">:</span><span class="w" id="mwCMo"> </span><span class="kt" id="mwCMs">DBResponse</span><span class="w" id="mwCMw"> </span><span class="o" id="mwCM0">=</span><span class="w" id="mwCM4"> </span><span class="k" id="mwCM8">await</span><span class="w" id="mwCNA"> </span><span class="nx" id="mwCNE">db</span><span class="p" id="mwCNI">.</span><span class="nx" id="mwCNM">post</span><span class="p" id="mwCNQ">({});</span> <span class="w" id="mwCNU"> </span><span class="kd" id="mwCNY">const</span><span class="w" id="mwCNc"> </span><span class="nx" id="mwCNg">doc</span><span class="o" id="mwCNk">:</span><span class="w" id="mwCNo"> </span><span class="kt" id="mwCNs">Document</span><span class="w" id="mwCNw"> </span><span class="o" id="mwCN0">=</span><span class="w" id="mwCN4"> </span><span class="k" id="mwCN8">await</span><span class="w" id="mwCOA"> </span><span class="nx" id="mwCOE">db</span><span class="p" id="mwCOI">.</span><span class="nx" id="mwCOM">get</span><span class="p" id="mwCOQ">(</span><span class="nx" id="mwCOU">response</span><span class="p" id="mwCOY">.</span><span class="nx" id="mwCOc">id</span><span class="p" id="mwCOg">);</span> <span class="w" id="mwCOk"> </span><span class="k" id="mwCOo">return</span><span class="w" id="mwCOs"> </span><span class="nx" id="mwCOw">doc</span><span class="p" id="mwCO0">;</span> <span class="p" id="mwCO4">}</span> <span class="k" id="mwCO8">async</span><span class="w" id="mwCPA"> </span><span class="kd" id="mwCPE">function</span><span class="w" id="mwCPI"> </span><span class="nx" id="mwCPM">main</span><span class="p" id="mwCPQ">()</span><span class="o" id="mwCPU">:</span><span class="w" id="mwCPY"> </span><span class="nb" id="mwCPc">Promise</span><span class="o" id="mwCPg"><</span><span class="ow" id="mwCPk">void</span><span class="o" id="mwCPo">></span><span class="w" id="mwCPs"> </span><span class="p" id="mwCPw">{</span> <span class="w" id="mwCP0"> </span><span class="k" id="mwCP4">try</span><span class="w" id="mwCP8"> </span><span class="p" id="mwCQA">{</span> <span class="w" id="mwCQE"> </span><span class="kd" id="mwCQI">const</span><span class="w" id="mwCQM"> </span><span class="nx" id="mwCQQ">doc</span><span class="o" id="mwCQU">:</span><span class="w" id="mwCQY"> </span><span class="kt" id="mwCQc">Document</span><span class="w" id="mwCQg"> </span><span class="o" id="mwCQk">=</span><span class="w" id="mwCQo"> </span><span class="k" id="mwCQs">await</span><span class="w" id="mwCQw"> </span><span class="nx" id="mwCQ0">createNewDoc</span><span class="p" id="mwCQ4">();</span> <span class="w" id="mwCQ8"> </span><span class="nx" id="mwCRA">console</span><span class="p" id="mwCRE">.</span><span class="nx" id="mwCRI">log</span><span class="p" id="mwCRM">(</span><span class="nx" id="mwCRQ">doc</span><span class="p" id="mwCRU">);</span> <span class="w" id="mwCRY"> </span><span class="p" id="mwCRc">}</span><span class="w" id="mwCRg"> </span><span class="k" id="mwCRk">catch</span><span class="w" id="mwCRo"> </span><span class="p" id="mwCRs">(</span><span class="nx" id="mwCRw">err</span><span class="o" id="mwCR0">:</span><span class="w" id="mwCR4"> </span><span class="kt" id="mwCR8">Error</span><span class="p" id="mwCSA">)</span><span class="w" id="mwCSE"> </span><span class="p" id="mwCSI">{</span> <span class="w" id="mwCSM"> </span><span class="nx" id="mwCSQ">console</span><span class="p" id="mwCSU">.</span><span class="nx" id="mwCSY">error</span><span class="p" id="mwCSc">(</span><span class="s2" id="mwCSg">"Error creating or fetching document:"</span><span class="p" id="mwCSk">,</span><span class="w" id="mwCSo"> </span><span class="nx" id="mwCSs">err</span><span class="p" id="mwCSw">);</span> <span class="w" id="mwCS0"> </span><span class="p" id="mwCS4">}</span> <span class="p" id="mwCS8">}</span> <span class="nx" id="mwCTA">main</span><span class="p" id="mwCTE">();</span>Node.js version 8 includes a utility that enables using the standard library callback-based methods as promises.
Kotlin
Kotlin uses coroutines with async() (from kotlinx.coroutines.CoroutineScope) and await() (from kotlinx.coroutines.Deferred<T>) methods, rather than true async/await keywords.
For example, the following uses async and await() methods for parallel execution.
<span id="mwCU8"></span><span class="k" id="mwCVA">import</span><span class="w" id="mwCVE"> </span><span class="nn" id="mwCVI">kotlinx.coroutines.*</span> <span class="k" id="mwCVM">import</span><span class="w" id="mwCVQ"> </span><span class="nn" id="mwCVU">kotlin.system.measureTimeMillis</span> <span class="kd" id="mwCVY">suspend</span><span class="w" id="mwCVc"> </span><span class="kd" id="mwCVg">fun</span><span class="w" id="mwCVk"> </span><span class="nf" id="mwCVo">fetchFirstData</span><span class="p" id="mwCVs">():</span><span class="w" id="mwCVw"> </span><span class="kt" id="mwCV0">String</span><span class="w" id="mwCV4"> </span><span class="p" id="mwCV8">{</span> <span class="w" id="mwCWA"> </span><span class="n" id="mwCWE">delay</span><span class="p" id="mwCWI">(</span><span class="m" id="mwCWM">1000</span><span class="p" id="mwCWQ">)</span><span class="w" id="mwCWU"> </span><span class="c1" id="mwCWY">// simulates a network call</span> <span class="w" id="mwCWc"> </span><span class="k" id="mwCWg">return</span><span class="w" id="mwCWk"> </span><span class="s" id="mwCWo">"Data from server A"</span> <span class="p" id="mwCWs">}</span> <span class="kd" id="mwCWw">suspend</span><span class="w" id="mwCW0"> </span><span class="kd" id="mwCW4">fun</span><span class="w" id="mwCW8"> </span><span class="nf" id="mwCXA">fetchSecondData</span><span class="p" id="mwCXE">():</span><span class="w" id="mwCXI"> </span><span class="kt" id="mwCXM">String</span><span class="w" id="mwCXQ"> </span><span class="p" id="mwCXU">{</span> <span class="w" id="mwCXY"> </span><span class="n" id="mwCXc">delay</span><span class="p" id="mwCXg">(</span><span class="m" id="mwCXk">1000</span><span class="p" id="mwCXo">)</span><span class="w" id="mwCXs"> </span><span class="c1" id="mwCXw">// simulates a network call</span> <span class="w" id="mwCX0"> </span><span class="k" id="mwCX4">return</span><span class="w" id="mwCX8"> </span><span class="s" id="mwCYA">"Data from server B"</span> <span class="p" id="mwCYE">}</span> <span class="kd" id="mwCYI">suspend</span><span class="w" id="mwCYM"> </span><span class="kd" id="mwCYQ">fun</span><span class="w" id="mwCYU"> </span><span class="nf" id="mwCYY">main</span><span class="p" id="mwCYc">()</span><span class="w" id="mwCYg"> </span><span class="o" id="mwCYk">=</span><span class="w" id="mwCYo"> </span><span class="n" id="mwCYs">coroutineScope</span><span class="w" id="mwCYw"> </span><span class="p" id="mwCY0">{</span> <span class="w" id="mwCY4"> </span><span class="kd" id="mwCY8">val</span><span class="w" id="mwCZA"> </span><span class="nv" id="mwCZE">time</span><span class="w" id="mwCZI"> </span><span class="o" id="mwCZM">=</span><span class="w" id="mwCZQ"> </span><span class="n" id="mwCZU">measureTimeMillis</span><span class="w" id="mwCZY"> </span><span class="p" id="mwCZc">{</span> <span class="w" id="mwCZg"> </span><span class="c1" id="mwCZk">// Start both network requests at the same time in the background</span> <span class="w" id="mwCZo"> </span><span class="kd" id="mwCZs">val</span><span class="w" id="mwCZw"> </span><span class="nv" id="mwCZ0">deferredOne</span><span class="p" id="mwCZ4">:</span><span class="w" id="mwCZ8"> </span><span class="n" id="mwCaA">Deferred</span><span class="o" id="mwCaE"><</span><span class="kt" id="mwCaI">String</span><span class="o" id="mwCaM">></span><span class="w" id="mwCaQ"> </span><span class="o" id="mwCaU">=</span><span class="w" id="mwCaY"> </span><span class="n" id="mwCac">async</span><span class="w" id="mwCag"> </span><span class="p" id="mwCak">{</span><span class="w" id="mwCao"> </span><span class="n" id="mwCas">fetchFirstData</span><span class="p" id="mwCaw">()</span><span class="w" id="mwCa0"> </span><span class="p" id="mwCa4">}</span> <span class="w" id="mwCa8"> </span><span class="kd" id="mwCbA">val</span><span class="w" id="mwCbE"> </span><span class="nv" id="mwCbI">deferredTwo</span><span class="p" id="mwCbM">:</span><span class="w" id="mwCbQ"> </span><span class="n" id="mwCbU">Deferred</span><span class="o" id="mwCbY"><</span><span class="kt" id="mwCbc">String</span><span class="o" id="mwCbg">></span><span class="w" id="mwCbk"> </span><span class="o" id="mwCbo">=</span><span class="w" id="mwCbs"> </span><span class="n" id="mwCbw">async</span><span class="w" id="mwCb0"> </span><span class="p" id="mwCb4">{</span><span class="w" id="mwCb8"> </span><span class="n" id="mwCcA">fetchSecondData</span><span class="p" id="mwCcE">()</span><span class="w" id="mwCcI"> </span><span class="p" id="mwCcM">}</span> <span class="w" id="mwCcQ"> </span><span class="c1" id="mwCcU">// Wait for both results to finish</span> <span class="w" id="mwCcY"> </span><span class="kd" id="mwCcc">val</span><span class="w" id="mwCcg"> </span><span class="nv" id="mwCck">resultOne</span><span class="w" id="mwCco"> </span><span class="o" id="mwCcs">=</span><span class="w" id="mwCcw"> </span><span class="n" id="mwCc0">deferredOne</span><span class="p" id="mwCc4">.</span><span class="na" id="mwCc8">await</span><span class="p" id="mwCdA">()</span> <span class="w" id="mwCdE"> </span><span class="kd" id="mwCdI">val</span><span class="w" id="mwCdM"> </span><span class="nv" id="mwCdQ">resultTwo</span><span class="w" id="mwCdU"> </span><span class="o" id="mwCdY">=</span><span class="w" id="mwCdc"> </span><span class="n" id="mwCdg">deferredTwo</span><span class="p" id="mwCdk">.</span><span class="na" id="mwCdo">await</span><span class="p" id="mwCds">()</span> <span class="w" id="mwCdw"> </span><span class="n" id="mwCd0">println</span><span class="p" id="mwCd4">(</span><span class="s" id="mwCd8">"Combined results: </span><span class="si" id="mwCeA">$</span><span class="n" id="mwCeE">resultOne</span><span class="s" id="mwCeI"> & </span><span class="si" id="mwCeM">$</span><span class="n" id="mwCeQ">resultTwo</span><span class="s" id="mwCeU">"</span><span class="p" id="mwCeY">)</span> <span class="w" id="mwCec"> </span><span class="p" id="mwCeg">}</span> <span class="w" id="mwCek"> </span><span class="n" id="mwCeo">println</span><span class="p" id="mwCes">(</span><span class="s" id="mwCew">"Completed in </span><span class="si" id="mwCe0">$</span><span class="n" id="mwCe4">time</span><span class="s" id="mwCe8"> ms"</span><span class="p" id="mwCfA">)</span> <span class="p" id="mwCfE">}</span>Perl
The Future::AsyncAwait module was the subject of a Perl Foundation grant in September 2018.
Python
Python 3.5 (2015) has added support for async/await as described in PEP 492 (written and implemented by Yury Selivanov).
<span id="mwCgk"></span><span class="kn" id="mwCgo">import</span><span class="w" id="mwCgs"> </span><span class="nn" id="mwCgw">asyncio</span> <span class="k" id="mwCg0">async</span> <span class="k" id="mwCg4">def</span><span class="w" id="mwCg8"> </span><span class="nf" id="mwChA">main</span><span class="p" id="mwChE">()</span> <span class="o" id="mwChI">-></span> <span class="kc" id="mwChM">None</span><span class="p" id="mwChQ">:</span> <span class="nb" id="mwChU">print</span><span class="p" id="mwChY">(</span><span class="s2" id="mwChc">"hello"</span><span class="p" id="mwChg">)</span> <span class="k" id="mwChk">await</span> <span class="n" id="mwCho">asyncio</span><span class="o" id="mwChs">.</span><span class="n" id="mwChw">sleep</span><span class="p" id="mwCh0">(</span><span class="mi" id="mwCh4">1</span><span class="p" id="mwCh8">)</span> <span class="nb" id="mwCiA">print</span><span class="p" id="mwCiE">(</span><span class="s2" id="mwCiI">"world"</span><span class="p" id="mwCiM">)</span> <span class="k" id="mwCiQ">if</span> <span class="vm" id="mwCiU">__name__</span> <span class="o" id="mwCiY">==</span> <span class="s2" id="mwCic">"__main__"</span><span class="p" id="mwCig">:</span> <span class="n" id="mwCik">asyncio</span><span class="o" id="mwCio">.</span><span class="n" id="mwCis">run</span><span class="p" id="mwCiw">(</span><span class="n" id="mwCi0">main</span><span class="p" id="mwCi4">())</span>
Rust
On November 7, 2019, async/await was released on the stable version of Rust. Async functions in Rust desugar to plain functions that return values that implement the std::future::Future trait. Currently they are implemented with a finite-state machine.
async is a specifier that marks an expression as returning a std::future::Future (rather than blocking the thread), while await is an operator (used with .await), which suspends execution until the std::future::Future result is ready.
<span id="mwClA"></span><span class="c1" id="mwClE">// In the crate's Cargo.toml, we need `futures = "0.3.0"` in the dependencies section,</span> <span class="c1" id="mwClI">// so we can use the futures crate</span> <span class="k" id="mwClM">extern</span><span class="w" id="mwClQ"> </span><span class="k" id="mwClU">crate</span><span class="w" id="mwClY"> </span><span class="n" id="mwClc">futures</span><span class="p" id="mwClg">;</span><span class="w" id="mwClk"> </span><span class="c1" id="mwClo">// There is no executor currently in the `std` library.</span> <span class="k" id="mwCls">use</span><span class="w" id="mwClw"> </span><span class="n" id="mwCl0">std</span><span class="p" id="mwCl4">::</span><span class="n" id="mwCl8">future</span><span class="p" id="mwCmA">::</span><span class="n" id="mwCmE">Future</span><span class="p" id="mwCmI">;</span> <span class="c1" id="mwCmM">// This desugars to something like</span> <span class="c1" id="mwCmQ">// `fn async_add_one(num: u32) -> impl Future<Output = u32>`</span> <span class="k" id="mwCmU">async</span><span class="w" id="mwCmY"> </span><span class="k" id="mwCmc">fn</span><span class="w" id="mwCmg"> </span><span class="nf" id="mwCmk">async_add_one</span><span class="p" id="mwCmo">(</span><span class="n" id="mwCms">num</span><span class="p" id="mwCmw">:</span><span class="w" id="mwCm0"> </span><span class="kt" id="mwCm4">u32</span><span class="p" id="mwCm8">)</span><span class="w" id="mwCnA"> </span><span class="p" id="mwCnE">-></span><span class="w" id="mwCnI"> </span><span class="kt" id="mwCnM">u32</span><span class="w" id="mwCnQ"> </span><span class="p" id="mwCnU">{</span> <span class="w" id="mwCnY"> </span><span class="n" id="mwCnc">num</span><span class="w" id="mwCng"> </span><span class="o" id="mwCnk">+</span><span class="w" id="mwCno"> </span><span class="mi" id="mwCns">1</span> <span class="p" id="mwCnw">}</span> <span class="k" id="mwCn0">async</span><span class="w" id="mwCn4"> </span><span class="k" id="mwCn8">fn</span><span class="w" id="mwCoA"> </span><span class="nf" id="mwCoE">example_task</span><span class="p" id="mwCoI">()</span><span class="w" id="mwCoM"> </span><span class="p" id="mwCoQ">{</span> <span class="w" id="mwCoU"> </span><span class="kd" id="mwCoY">let</span><span class="w" id="mwCoc"> </span><span class="n" id="mwCog">number</span><span class="w" id="mwCok"> </span><span class="o" id="mwCoo">=</span><span class="w" id="mwCos"> </span><span class="n" id="mwCow">async_add_one</span><span class="p" id="mwCo0">(</span><span class="mi" id="mwCo4">5</span><span class="p" id="mwCo8">).</span><span class="k" id="mwCpA">await</span><span class="p" id="mwCpE">;</span> <span class="w" id="mwCpI"> </span><span class="fm" id="mwCpM">println!</span><span class="p" id="mwCpQ">(</span><span class="s" id="mwCpU">"5 + 1 = {}"</span><span class="p" id="mwCpY">,</span><span class="w" id="mwCpc"> </span><span class="n" id="mwCpg">number</span><span class="p" id="mwCpk">);</span> <span class="p" id="mwCpo">}</span> <span class="k" id="mwCps">fn</span><span class="w" id="mwCpw"> </span><span class="nf" id="mwCp0">main</span><span class="p" id="mwCp4">()</span><span class="w" id="mwCp8"> </span><span class="p" id="mwCqA">{</span> <span class="w" id="mwCqE"> </span><span class="c1" id="mwCqI">// Creating the Future does not start the execution.</span> <span class="w" id="mwCqM"> </span><span class="kd" id="mwCqQ">let</span><span class="w" id="mwCqU"> </span><span class="n" id="mwCqY">future</span><span class="w" id="mwCqc"> </span><span class="o" id="mwCqg">=</span><span class="w" id="mwCqk"> </span><span class="n" id="mwCqo">example_task</span><span class="p" id="mwCqs">();</span> <span class="w" id="mwCqw"> </span><span class="c1" id="mwCq0">// The `Future` only executes when we actually poll it, unlike JavaScript.</span> <span class="w" id="mwCq4"> </span><span class="n" id="mwCq8">futures</span><span class="p" id="mwCrA">::</span><span class="n" id="mwCrE">executor</span><span class="p" id="mwCrI">::</span><span class="n" id="mwCrM">block_on</span><span class="p" id="mwCrQ">(</span><span class="n" id="mwCrU">future</span><span class="p" id="mwCrY">);</span> <span class="p" id="mwCrc">}</span>Swift
Swift 5.5 (2021) added support for async/await as described in SE-0296.
<span id="mwCsQ"></span><span class="kd" id="mwCsU">func</span><span class="w" id="mwCsY"> </span><span class="nf" id="mwCsc">getNumber</span><span class="p" id="mwCsg">()</span><span class="w" id="mwCsk"> </span><span class="k" id="mwCso">async</span><span class="w" id="mwCss"> </span><span class="kr" id="mwCsw">throws</span><span class="w" id="mwCs0"> </span><span class="p" id="mwCs4">-></span><span class="w" id="mwCs8"> </span><span class="nb" id="mwCtA">Int</span><span class="w" id="mwCtE"> </span><span class="p" id="mwCtI">{</span> <span class="w" id="mwCtM"> </span><span class="k" id="mwCtQ">try</span><span class="w" id="mwCtU"> </span><span class="k" id="mwCtY">await</span><span class="w" id="mwCtc"> </span><span class="n" id="mwCtg">Task</span><span class="p" id="mwCtk">.</span><span class="n" id="mwCto">sleep</span><span class="p" id="mwCts">(</span><span class="n" id="mwCtw">nanoseconds</span><span class="p" id="mwCt0">:</span><span class="w" id="mwCt4"> </span><span class="mi" id="mwCt8">1_000_000_000</span><span class="p" id="mwCuA">)</span> <span class="w" id="mwCuE"> </span><span class="k" id="mwCuI">return</span><span class="w" id="mwCuM"> </span><span class="mi" id="mwCuQ">42</span> <span class="p" id="mwCuU">}</span> <span class="n" id="mwCuY">Task</span><span class="w" id="mwCuc"> </span><span class="p" id="mwCug">{</span> <span class="w" id="mwCuk"> </span><span class="kd" id="mwCuo">let</span><span class="w" id="mwCus"> </span><span class="nv" id="mwCuw">first</span><span class="w" id="mwCu0"> </span><span class="p" id="mwCu4">=</span><span class="w" id="mwCu8"> </span><span class="k" id="mwCvA">try</span><span class="w" id="mwCvE"> </span><span class="k" id="mwCvI">await</span><span class="w" id="mwCvM"> </span><span class="n" id="mwCvQ">getNumber</span><span class="p" id="mwCvU">()</span> <span class="w" id="mwCvY"> </span><span class="kd" id="mwCvc">let</span><span class="w" id="mwCvg"> </span><span class="nv" id="mwCvk">second</span><span class="w" id="mwCvo"> </span><span class="p" id="mwCvs">=</span><span class="w" id="mwCvw"> </span><span class="k" id="mwCv0">try</span><span class="w" id="mwCv4"> </span><span class="k" id="mwCv8">await</span><span class="w" id="mwCwA"> </span><span class="n" id="mwCwE">getNumber</span><span class="p" id="mwCwI">()</span> <span class="w" id="mwCwM"> </span><span class="bp" id="mwCwQ">print</span><span class="p" id="mwCwU">(</span><span class="bp" id="mwCwY">first</span><span class="w" id="mwCwc"> </span><span class="o" id="mwCwg">+</span><span class="w" id="mwCwk"> </span><span class="n" id="mwCwo">second</span><span class="p" id="mwCws">)</span> <span class="p" id="mwCww">}</span>Benefits and criticisms
The async/await pattern is especially attractive to language designers of languages that do not have or control their own runtime, as async/await can be implemented solely as a transformation to a state machine in the compiler.
Supporters claim that asynchronous, non-blocking code can be written with async/await that looks almost like traditional synchronous, blocking code. In particular, it has been argued that await is the best way of writing asynchronous code in message-passing programs; in particular, being close to blocking code, readability and the minimal amount of boilerplate code were cited as await benefits.
Critics of async/await note that the pattern tends to cause surrounding code to be asynchronous too; and that its contagious nature splits languages' library ecosystems between synchronous and asynchronous libraries and APIs, an issue often referred to as "function coloring". Alternatives to async/await that do not suffer from this issue are called "colorless". Examples of colorless designs include Go's goroutines and Java's virtual threads.

