HOME

TheInfoList



OR:

In computer programming, the async/await pattern is a syntactic feature of many programming languages that allows an
asynchronous Asynchrony is the state of not being in synchronization. Asynchrony or asynchronous may refer to: Electronics and computing * Asynchrony (computer programming), the occurrence of events independent of the main program flow, and ways to deal with ...
, non-blocking
function Function or functionality may refer to: Computing * Function key, a type of key on computer keyboards * Function model, a structured representation of processes in a system * Function object or functor or functionoid, a concept of object-oriente ...
to be structured in a way similar to an ordinary synchronous function. It is semantically related to the concept of a
coroutine Coroutines are computer program components that generalize subroutines for non-preemptive multitasking, by allowing execution to be suspended and resumed. Coroutines are well-suited for implementing familiar program components such as cooperativ ...
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# 5.0, C++20,
Python Python may refer to: Snakes * Pythonidae, a family of nonvenomous snakes found in Africa, Asia, and Australia ** ''Python'' (genus), a genus of Pythonidae found in Africa and Asia * Python (mythology), a mythical serpent Computing * Python (pr ...
3.5, F#,
Hack Hack may refer to: Arts, entertainment, and media Games * ''Hack'' (Unix video game), a 1984 roguelike video game * ''.hack'' (video game series), a series of video games by the multimedia franchise ''.hack'' Music * ''Hack'' (album), a 199 ...
,
Julia Julia is usually a feminine given name. It is a Latinate feminine form of the name Julio and Julius. (For further details on etymology, see the Wiktionary entry "Julius".) The given name ''Julia'' had been in use throughout Late Antiquity (e. ...
,
Dart Dart or DART may refer to: * Dart, the equipment in the game of darts Arts, entertainment and media * Dart (comics), an Image Comics superhero * Dart, a character from ''G.I. Joe'' * Dart, a ''Thomas & Friends'' railway engine character * Da ...
, Kotlin 1.1,
Rust Rust is an iron oxide, a usually reddish-brown oxide formed by the reaction of iron and oxygen in the catalytic presence of water or air moisture. Rust consists of hydrous iron(III) oxides (Fe2O3·nH2O) and iron(III) oxide-hydroxide (FeO(OH) ...
1.39, Nim 0.9.4, JavaScript
ES2017 ECMAScript is a JavaScript standard developed by Ecma International. Since 2015, major versions have been published every June. ECMAScript 2022, the 13th and current version, was released in June 2022. Versions In June 2004, Ecma International p ...

Swift 5.5
and Zig, with some experimental work in extensions, beta versions, and particular implementations of Scala.


History

F# added asynchronous workflows with await points in version 2.0 in 2007. This influenced the async/await mechanism added to C#. Microsoft released a version of C# with async/await for the first time in the Async CTP (2011). And were later officially released in C# 5 (2012). Haskell lead developer
Simon Marlow Simon Marlow is a British computer programmer, author, and co-developer of the Glasgow Haskell Compiler (GHC). He and Simon Peyton Jones won the SIGPLAN Programming Languages Software Award in 2011 for their work on GHC. Marlow's book Parallel ...
created the async package in 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 with 1 new keyword async and a lazy eval await pattern. 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 wit
version 5.5
in 2021, adding 2 new keywords async and await. This was released alongside a concrete implementation of the
Actor model The actor model in computer science is a mathematical model of concurrent computation that treats ''actor'' as the universal primitive of concurrent computation. In response to a message it receives, an actor can: make local decisions, create more ...
with the actor keyword which uses async/await to mediate access to each actor from outside.


Example C#

The C# function below, which downloads a resource from a URI and returns the resource's length, uses this async/await pattern: public async Task FindPageSizeAsync(Uri uri) * First, the async keyword indicates to C# that the method is asynchronous, meaning that it may use an arbitrary number of await expressions and will bind the result to a promise. * The return type, Task<T>, is C#'s analogue to the concept of a promise, and here is indicated to have a result value of type int. * The first expression to execute when this method is called will be new HttpClient().GetByteArrayAsync(uri), which is another asynchronous method returning a Task<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, unrejected Task<byte[]> to this function. * With the await keyword attached to the Task, this function will immediately proceed to return a Task<int> to its caller, who may then continue on with other processing as needed. * Once GetByteArrayAsync() finishes its download, it will resolve the Task it returned with the downloaded data. This will trigger a callback and cause FindPageSizeAsync() to continue execution by assigning that value to data. * Finally, the method returns data.Length, a simple integer indicating the length of the array. The compiler re-interprets this as resolving the Task it 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 you 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
continuation In computer science, a continuation is an abstract representation of the control state of a computer program. A continuation implements ( reifies) the program control state, i.e. the continuation is a data structure that represents the computat ...
s 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 Bytecode (also called portable code or p-code) is a form of instruction set designed for efficient execution by a software interpreter. Unlike human-readable source code, bytecodes are compact numeric codes, constants, and references (normall ...
format: public Task FindPageSizeAsync(Uri uri) 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: var a = state.a; var client = new HttpClient(); var data = await client.GetByteArrayAsync(uri); Debug.Assert(a

state.a); // Potential failure, as value of state.a may have been changed // by the handler of potentially intervening event. return data.Length;


In F#

F# added asynchronous workflows in 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: let asyncSumPageSizes (uris: #seq) : Async = async


In C#

The async/await pattern in C# is available as of version 5.0, which Microsoft refers to as the task-based asynchronous pattern (TAP). Async methods usually return either void, Task, Task<T>, ValueTask or 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.Stephen Cleary
Async/Await - Best Practices in Asynchronous Programming
/ref> 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. public async Task SumPageSizesAsync(ICollection uris)


In Scala

In the experimental Scala-async extension to Scala, is a "method", although it does not operate like an ordinary method. Furthermore, unlike in C# 5.0 in which a method must be marked as async, in Scala-async, a ''block'' of code is surrounded by an async "call".


How it works

In Scala-async, is actually implemented using a Scala macro, which causes the
compiler In computing, a compiler is a computer program that translates computer code written in one programming language (the ''source'' language) into another language (the ''target'' language). The name "compiler" is primarily used for programs th ...
to emit different code, and produce a finite state machine implementation (which is considered to be more efficient than a monadic implementation, but less convenient to write by hand). There are plans for Scala-async to support a variety of different implementations, including non-asynchronous ones.


In Python

Python 3.5 (2015) has added support for async/await as described in PEP 492 (written and implemented by Yury Selivanov). import asyncio async def main(): print("hello") await asyncio.sleep(1) print("world") asyncio.run(main())


In JavaScript

The await operator in JavaScript can only be used from inside an async function. 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 In computing and computer programming, exception handling is the process of responding to the occurrence of ''exceptions'' – anomalous or exceptional conditions requiring special processing – during the execution of a program. In general, a ...
). If the parameter is not a promise, 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. Here's an example (modified from this article): async function createNewDoc() async function main() main();
Node.js Node.js is an open-source server environment. Node.js is cross-platform and runs on Windows, Linux, Unix, and macOS. Node.js is a back-end JavaScript runtime environment. Node.js runs on the V8 JavaScript Engine and executes JavaScript cod ...
version 8 includes a utility that enables using the standard library callback-based methods as promises.


In C++

In C++, await (named co_await in C++) has been officially merged into version 20. Support for it, coroutines, and the keywords such as co_await is available in GCC and MSVC compilers while
Clang Clang is a compiler front end for the C, C++, Objective-C, and Objective-C++ programming languages, as well as the OpenMP, OpenCL, RenderScript, CUDA, and HIP frameworks. It acts as a drop-in replacement for the GNU Compiler Collection (GCC) ...
has partial support. It is worth noting that std::promise and std::future, although it would seem that they would be awaitable objects, implement none of the machinery required to be returned from coroutines and be awaited using co_await. Programmers 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. Details can be found on cppreference. #include #include "CustomAwaitableTask.h" using namespace std; CustomAwaitableTask add(int a, int b) CustomAwaitableTask test() int main()


In C

There's no official support for await/async in the C language yet. Some coroutine libraries such as s_task simulate the keywords await/async with macros. #include #include "s_task.h" // define stack memory for tasks int g_stack_main 4 * 1024 / sizeof(int) int g_stack0 4 * 1024 / sizeof(int) int g_stack1 4 * 1024 / sizeof(int) void sub_task(__async__, void* arg) void main_task(__async__, void* arg) int main(int argc, char* argv)


In Perl 5

The Future::AsyncAwait module was the subject of a Perl Foundation grant in September 2018.


In 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 Future trait. Currently they are implemented with a finite state machine. // In the crate's Cargo.toml, we need `futures = "0.3.0"` in the dependencies section, // so we can use the futures crate extern crate futures; // There is no executor currently in the `std` library. // This desugars to something like // `fn async_add_one(num: u32) -> impl Future` async fn async_add_one(num: u32) -> u32 async fn example_task() fn main()


In Swift

Swift 5.5 (2021) added support for async/await as described in SE-0296. func getNumber() async throws -> Int Task


Benefits and criticisms

A significant benefit of the async/await pattern in languages that support it is that asynchronous, non-blocking code can be written, with minimal overhead, and looking 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 In computer programming, boilerplate code, or simply boilerplate, are sections of code that are repeated in multiple places with little to no variation. When using languages that are considered ''verbose'', the programmer must write a lot of boile ...
were cited as await benefits.'No Bugs' Hare
Eight ways to handle non-blocking returns in message-passing programs
CPPCON, 2018
As a result, async/await makes it easier for most programmers to reason about their programs, and await tends to promote better, more robust non-blocking code in applications that require it. Such applications range from programs presenting graphical user interfaces to massively scalable stateful server-side programs, such as games and financial applications. When criticising await, it has been noted that await tends to cause surrounding code to be asynchronous too; on the other hand, it has been argued that this contagious nature of the code (sometimes being compared to a "zombie virus") is inherent to all kinds of asynchronous programming, so await as such is not unique in this regard.


See also

*
Coroutines Coroutines are computer program components that generalize subroutines for non-preemptive multitasking, by allowing execution to be suspended and resumed. Coroutines are well-suited for implementing familiar program components such as cooperativ ...
*
Continuation-passing style In functional programming, continuation-passing style (CPS) is a style of programming in which control is passed explicitly in the form of a continuation. This is contrasted with direct style, which is the usual style of programming. Gerald Jay Sus ...
* Direct style *
Cooperative multitasking Cooperative multitasking, also known as non-preemptive multitasking, is a style of computer multitasking in which the operating system never initiates a context switch from a running process to another process. Instead, in order to run multiple a ...


References

{{reflist Control flow