This covers the asynchronous programming model supported by various programming languages, using the async and await keywords.
Several programming languages support an asynchronous programming model using co-routines, with the async
and await
keywords.
Support for the model was added to
- C# and VB in VS2012
- Python in 3.5
- ECMAScript in ECMAScript 2017
- Rust in 1.39
- C++ in C++20
- Swift in Swift 5.5
C# and Visual Studio
Asynchronous programming with async
and await
was introduced with C# 5.0 in Visual Studio 2012. The run-time support for this language concept is a part of .NET 4.5 / Windows Phone 8 / Windows 8.x Store Runtime.
It's also possible to use async/await
and target .NET 4.0 / Windows Phone 7.1 / Silverlight 4 / MonoTouch / MonoDroid / Portable Class Libraries, with Visual Studio 2012+ and Microsoft.Bcl.Async
NuGet package, which is licensed for production code.
Async CTP add-on for VS2010 SP1 is also available, but it is not suitable for product development.
Python
Similar syntax was introduced to Python 3.5 (see PEP 492 - Coroutines with async and await syntax.
Previously, it was possible to write co-routines using generators; with the introduction of await
and async
co-routines were lifted to a native language feature.
C++
Coroutines
is introduced in C++20
. Using the co_await
operator results in suspended execution until resumed. Values can be returned using co_yield
and co_return
keywords which correspond to suspending and completing execution, respectively.
Swift
The async
-await
pattern was introduced in Swift 5.5 at WWDC 2021, as part of a broader Swift concurrency initiative. Historically, asynchronous patterns were achieved through the use of Grand Central Dispatch (GCD, grand-central-dispatch) and “completion handler closure” patterns. The Swift concurrency aims to provide a more intuitive asynchronous coding environment.
ECMAScript
The async
and await
keywords were first reserved in the ECMAScript 2016 specification and then their use and behavior was fully-specified in the ECMAScript 2017 specification.
Historically, ECMAScript offered “promises”, an improvement over traditional callback patterns, where this sort of looping and exception handling is challenging. Task.js
and similar libraries further refined promises, to further simplify the process. But with async
functions, all the remaining boilerplate is removed, leaving only the semantically meaningful code in the program text.
Asynchronous vs multi-threaded
The async
-await
pattern simplifies the writing of asynchronous code. While it is frequently used in multi-threaded environments, it should be noted that “asynchronous” and “multi-threaded” represent two different concepts. The async
and await
keywords merely allow us to represent relationships and dependencies between asynchronous tasks in a more natural manner, which may be distinct from the mechanism to run code on a different thread. The async
-await
pattern offers great utility in a multi-threaded environment, but it is not, itself, the multi-threaded mechanism.
Resources:
C#
- Lucian Wischik, video series: Six Essential Tips For Async
- Stephen Toub and Parallel Team's blog - Async/Await FAQ
- Stephen Cleary's blog - Async and Await
- Stephan Cleary's post - There Is No Thread
- MSDN Magazine - Best Practices in Asynchronous Programming
- MSDN Magazine - It's All About the SynchronizationContext
- MSDN Magazine - Pause and Play with Await
- MSDN Magazine - Async Performance: Understanding the Costs of Async and Await
- MSDN - C# Language Specification for Asynchronous Functions
- MSDN - Task-based Asynchronous Pattern
- MSDN - Whitepaper: Asynchrony in .NET
- Docs - Asynchronous programming (C#)
- Docs - Asynchronous Programming with Async and Await (Visual Basic)
C++
Swift
Related:
- task-parallel-library - Task Parallel Library
- coyote - The Coyote open source asynchronous programming framework
- swift-concurrency - Swift Concurrency