- C# - Home
- C# - Overview
- C# - Environment
- C# - Program Structure
- C# - Basic Syntax
- C# - Data Types
- C# - Type Conversion
- C# - Variables
- C# - Constants
- C# - Operators
- C# - Arithmetic Operators
- C# - Assignment Operators
- C# - Relational Operators
- C# - Logical Operators
- C# - Bitwise Operators
- C# - Miscellaneous Operators
- C# - Operators Precedence
- C# Conditional Statements
- C# - Decision Making
- C# - If
- C# - If Else
- C# - Nested If
- C# - Switch
- C# - Nested Switch
- C# - Switch Expressions
- C# Control Statements
- C# - Loops
- C# - For Loop
- C# - While Loop
- C# - Do While Loop
- C# - Nested Loops
- C# - Break
- C# - Continue
- C# - Foreach Loop
- C# - Goto Statement
- C# OOP & Data Handling
- C# - Encapsulation
- C# - Methods
- C# - Nullables
- C# - Arrays
- C# - Strings
- C# - Structure
- C# - Enums
- C# - Classes
- C# - Inheritance
- C# - Polymorphism
- C# - Operator Overloading
- C# - Interfaces
- C# - Namespaces
- C# - Preprocessor Directives
- C# - Regular Expressions
- C# - Exception Handling
- C# - File I/O
- C# Advanced Tutorial
- C# - Attributes
- C# - Reflection
- C# - Properties
- C# - Indexers
- C# - Delegates
- C# - Events
- C# - Collections
- C# - Generics
- C# - LINQ
- C# - IEnumerable vs IEnumerator
- C# - Anonymous Methods
- C# - Unsafe Codes
- C# - Tasks and Parallel Programming
- C# - Multithreading
- C# - Extension Methods
- C# - Async and Await
- C# Modern Features
- C# - Tuples
- C# - Pattern Matching Enhancements
- C# - Nullable Reference Types
- C# - What's New in C# 11 / 12 / 13
- C# Practical & Advanced Usage
- C# - JSON & XML Handling
Async / Await in C#
In C#, 'async' and 'await' are both keywords fundamental to asynchronous programming. They enable the creation of responsive applications by preventing the main thread from being blocked during long-running operations.
Asynchronous Programming in C#
The Task Asynchronous Programming (TAP) model in C# makes writing asynchronous code easier and cleaner. It lets you write code just like normal sequential code, but the difference is that tasks run in the background without blocking the main thread. This means your program can keep working on other things while waiting for a task (like downloading data or reading a file) to finish. The compiler takes care of managing the flow, so your code stays simple and easy to read.
What is Async and Await in C#
C# provides built-in support for asynchronous programming through the async and await keywords. These keywords allow developers to perform non-blocking operations, such as file handling, I/O network calls or database queries, without freezing the main thread.
Asynchronous programming improves application responsiveness by keeping your app active, smooth, and quick to respond, even during long operations. This is particularly true in UI-based and server-side applications, where blocking operations can break performance.
Listed here are some of the important points on asynchronous programming −
- async and await make writing asynchronous code simple and easy to read.
- Use the async keyword before a method, lambda, or anonymous function to mark it as asynchronous.
- Use await inside an async method to pause the code until a task finishes.
- An async method usually returns Task, Task<TResult>, or void (used only for event handlers).
- While waiting for a task, the program doesnât block the main thread - it stays responsive.
Declaration of Async and Await
In C#, we can use the async and await keywords together to define and work with asynchronous methods.
async Task MethodNameAsync() {
await SomeAsyncOperation();
}
Explanation
- The async keyword is added before the method declaration to mark it as asynchronous.
- The await keyword is used inside the method to wait for another asynchronous operation to complete.
- The code after await runs only after the awaited task is finished, keeping the main thread free.
Let's look at an example of how the program waits for "DownloadDataAsync()" to finish without blocking other code from running.
public async Task GetDataAsync() {
// Calling just random function to show declaration.
string data = await DownloadDataAsync();
Console.WriteLine(data);
}
C# async and await Best Practices
Let's understand what should follow to ensure that we are performing asynchronous tasks perfectly −
- An async method should have at least one await; otherwise, it runs like a synchronous method.
- Use async Task for methods that do asynchronous work but donât return a value.
- Use async Task<TResult> for methods that return a value.
- Avoid async void except for event handlers.
- Donât use blocking calls like .Result or .Wait(), as they can freeze the program or cause deadlocks.
Example: Asynchronous Program with Task.Delay()
In this example, we are using async and await with the delay method to show the message after a specific delay −
using System;
using System.Threading.Tasks;
class myProgram {
static async Task Main() {
Console.WriteLine("Hi Tutorialspoint your task will be completing within 2 seconds");
// Delay is function to delay a task
await Task.Delay(2000);
Console.WriteLine("Hey task completed after 2Secs.");
}
}
When you run this code, it will produce the following output −
Hi Tutorialspoint your task will be completing within 2 seconds Hey task completed after 2Secs.
Example: Running Multiple Tasks with async and await
In the following example, we manage the multiple tasks in a single code without blocking the other tasks using the 'async' and 'await' keywords −
using System;
using System.Threading.Tasks;
class myProgram {
static async Task Main() {
Console.WriteLine("Starting multiple tasks...");
// Run multiple async tasks
Task fetchTask = FetchDataAsync();
Task saveTask = SaveDataAsync();
Task notifyTask = SendNotificationAsync();
// Wait for all tasks to complete
await Task.WhenAll(fetchTask, saveTask, notifyTask);
Console.WriteLine("All tasks completed successfully!");
}
static async Task FetchDataAsync() {
Console.WriteLine("Fetching data...");
await Task.Delay(2000);
Console.WriteLine("Data fetched successfully!");
}
static async Task SaveDataAsync() {
Console.WriteLine("Saving data...");
await Task.Delay(3000);
Console.WriteLine("Data saved successfully!");
}
static async Task SendNotificationAsync() {
Console.WriteLine("Sending notification...");
await Task.Delay(1000);
Console.WriteLine("Notification sent!");
}
}
Following is the output −
Starting multiple tasks... Fetching data... Saving data... Sending notification... Notification sent! Data fetched successfully! Data saved successfully! All tasks completed successfully!
Example: Return the Square of a Number
In the following example, we are performing an async task with a return type. Here we are returning the square of a number.
using System;
using System.Threading.Tasks;
class MyProgram {
static async Task Main() {
int result = await CalculateSquare(10, 2);
Console.WriteLine("Square: " + result);
}
static async Task<int> CalculateSquare(int a, int b) {
return await Task.Run(() => (int)Math.Pow(a, b));
}
}
Following is the output -
Square: 100
Example: Read File Content Asynchronously
In the following example, we read a File, Asynchronously using async and await in C#
using System;
using System.IO;
using System.Threading.Tasks;
class myProgram {
static async Task Main() {
string path = "tutorialspoint.txt";
string content = await ReadFileAsync(path);
Console.WriteLine("Content of the File:\n" + content);
}
static async Task<string> ReadFileAsync(string filePath) {
using (StreamReader reader = new StreamReader(filePath)) {
return await reader.ReadToEndAsync();
}
}
}
The above code will not run on the online compiler; it will run on the local system, and you should pass the path of the "tutorialspoint.txt" file.
Conclusion
Async and await in C# make the code easy to run tasks without blocking the other thread or task. They help keep applications smooth and responsive while performing background operations.