Lot of time I have been asked the question around Async and Await during interviews.
Here is I am trying to consolidate my understanding around these keywords with some snippets.
What is Asynchronous Programming?:
In Asynchronous programming methods are run without blocking the main thread.
**Async **Keyword: Marks a method as asynchronous, allowing the use of await.
**Await **Keyword: Suspends execution until the awaited task is complete.
Task and Task: Core types representing asynchronous operations.
Why Use await in Methods?
The await keyword is used to pause execution of the calling method until the awaited asynchronous operation completes. This allows other tasks (like UI updates or other background operations) to run without blocking the thread.
When Not to Use await
In some cases, you might not need await:
Fire-and-Forget: When the result of a task isn’t needed, you can call it without await.
LogDataAsync("Message"); // Fire-and-forget (but use cautiously)
Aggregating Multiple Tasks: You can combine tasks using Task.WhenAll without awaiting each individually.
var tasks = new[] { Task1(), Task2() };
await Task.WhenAll(tasks);
Returning Tasks: When a method simply returns a task to its caller, you don't need await unless you want to handle exceptions or perform additional work.
static Task<string> FetchDataAsync() => Task.FromResult("Data");
To make the operations parallel or concurrent, you need to execute multiple tasks simultaneously without waiting for one task to complete before starting the next. This can improve performance, especially for I/O-bound operations like database calls, API requests, or file logging.
In the banking example, here’s how parallelism or concurrency can be applied:
Understanding Parallelism vs Concurrency
- Parallelism: Tasks run at the same time on multiple threads, often leveraging multiple CPU cores. It’s best for CPU-bound tasks.
- Concurrency: Tasks appear to run simultaneously by interleaving execution, often best for I/O-bound tasks (e.g., waiting for a database or API response).
In financial example:
- Concurrent tasks: Fetching account balance, calling external APIs, and logging transactions.
- Parallel tasks: Performing multiple transfers or operations simultaneously.
Banking Example for Parallelism
Scenario
We'll make the following tasks run concurrently:
- Checking the account balance.
- Making the API call for fund transfer.
- Logging the transaction.
These tasks are independent and can run simultaneously.
Updated Code
using System;
using System.IO;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
class BankingService
{
private static readonly HttpClient _httpClient = new HttpClient();
public async Task MainAsync()
{
Console.WriteLine("Transaction started...");
// Step 1: Run tasks concurrently
var checkBalanceTask = CheckAccountBalanceFromDbAsync("123456");
var transferTask = TransferFundsToExternalBankAsync("123456", "654321", 500);
var logTask = LogTransactionAsync("123456", "654321", 500);
// Step 2: Await all tasks to complete
await Task.WhenAll(checkBalanceTask, transferTask, logTask);
Console.WriteLine("Transaction completed successfully.");
}
// Simulate checking account balance (database operation)
private async Task<decimal> CheckAccountBalanceFromDbAsync(string accountId)
{
Console.WriteLine("Querying account balance from database...");
await Task.Delay(500); // Simulate delay for database query
Console.WriteLine("Account balance fetched.");
return 1000.00m; // Assume a balance of $1000
}
// Simulate transferring funds to another bank using an external API
private async Task TransferFundsToExternalBankAsync(string fromAccountId, string toAccountId, decimal amount)
{
Console.WriteLine($"Transferring ${amount} from {fromAccountId} to {toAccountId}...");
var payload = new
{
fromAccountId,
toAccountId,
amount
};
var jsonPayload = JsonSerializer.Serialize(payload);
var content = new StringContent(jsonPayload, System.Text.Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync("https://mock-bank-api.com/transfer", content);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Funds transferred successfully.");
}
else
{
Console.WriteLine("Transfer failed.");
}
}
// Simulate logging the transaction (write to a file)
private async Task LogTransactionAsync(string fromAccountId, string toAccountId, decimal amount)
{
string logMessage = $"Transaction: ${amount} from {fromAccountId} to {toAccountId} at {DateTime.Now}\n";
Console.WriteLine("Logging transaction...");
await File.AppendAllTextAsync("transaction_log.txt", logMessage);
Console.WriteLine("Transaction logged.");
}
}
// Entry point
class Program
{
static async Task Main(string[] args)
{
var service = new BankingService();
await service.MainAsync();
}
}
How This Works
-
Concurrent Execution:
-
Task.WhenAll
allows multiple tasks to run concurrently. - The following three tasks start simultaneously:
- Checking the account balance.
- Transferring funds.
- Logging the transaction.
-
-
Efficiency:
- Each task is asynchronous and doesn’t block the thread while waiting for I/O operations (e.g., database query, HTTP request, or file writing).
- The tasks do not depend on each other and can run independently.
-
Result Handling:
- If you need the result from
CheckAccountBalanceFromDbAsync
, you can await it separately while other tasks still execute:
decimal balance = await checkBalanceTask;
- If you need the result from
Key Concepts:
Task.WhenAll
- Waits for all tasks to complete.
- If any task fails, it throws an
AggregateException
containing details of all failures. - Example:
await Task.WhenAll(task1, task2, task3);
Task.WhenAny
- Waits for the first task to complete (useful for racing or fallback scenarios).
- Example:
var firstCompletedTask = await Task.WhenAny(task1, task2, task3);
Advantages of Parallel/Concurrent Execution
-
Improved Performance:
- Independent tasks run simultaneously, reducing the overall time.
-
Non-Blocking Execution:
- The main thread remains free to handle other work.
-
Scalability:
- Particularly useful in high-throughput systems like financial applications.
Top comments (0)