Asynchronous programming is needed to write code that can handle a long-running requests (like querying a database, calling an API, or reading a large file) instead of just stopping and waiting for response.
This Async Programming is essential for having a responsive application. The UI freeze without using async in mobile app and using async programming on web servers allows handling a massive number of requests instead of being blocked by one slow request.
using sync means the main thread will be blocked till it finish the current task.

while via async the main thread won't get blocked and is immediately freed up to do other things. Whenever the task finishes, the main thread will pick up the result and continue.
The Analogy: Doing Chores
Imagine it's a weekend and you have to do some Cores at home. you might need to do laundries, washing some dishes and probably you want to watch a new episode of your favourite series. So you probably first load washer machine and start the washing cycle and while machine is washing the laundries you might fill up the dish washer and start the machine. While both machines are working so you have time for watching a new episode.
all the step above you will do them async. It means that you are not standing in front of washer doing nothing till the cycle finish. you have just start the task and then you are free to do some other tasks. you are the main thread and by starting each machine you starting a task and free up the main thread.
Syntax at a glance
Here is the example using analogy described above
You only need to know three main things.
Task: The promise
This object represents the work-in-progress. Think of it as a "receipt" we get from the washer. It's not the clean clothes, but it's the promise of clean clothes.
-
Task: Use this for an async method that doesn't return a value (like void). -
Task<T>: Use this for an async method that does return a value. (e.g., Task promises to give you a string eventually).
async: The marker
We add this keyword to a method signature (e.g., public async Task DoLaundry()). It simply "unlocks" the ability to use the await keyword inside that method. It's just like a signal to the compiler.
await: The "Pause Button"
This is the operator we need to put in front of a Task (e.g., string result = await GetSomeDataAsync();).and It actually tells the compiler that here is a long-running task. Compiler can pause this method here, give control back to the caller, and later when the task is finished it can come back to this exact line to continue.
Scenario: Pricing service
Consider you have a train ticket and you want to calculate the total price for the customers. let's consider for each ticket we have Ticket Price, Insurance price, Vat and Admin Fee that needs to get calculated.
Sync Solution:
so here we have multiple fees need to calculated and each will take couple of seconds:
private int GetTicketPrice()
{
Console.WriteLine($" getting Ticket Price at {DateTime.Now}");
Thread.Sleep(TimeSpan.FromSeconds(0.5));
return 20;
}
private int GetInsurancePrice()
{
Console.WriteLine($" getting insurance Price at {DateTime.Now}");
Thread.Sleep(TimeSpan.FromSeconds(1));
return 5;
}
private int CalculateVat()
{
Console.WriteLine($" Calculating Vat at {DateTime.Now}");
Thread.Sleep(TimeSpan.FromSeconds(5));
return 1;
}
private int CalculateAdminFee()
{
Console.WriteLine($" Calculating Admin fee at {DateTime.Now}");
Thread.Sleep(TimeSpan.FromSeconds(2));
return 2;
}
and we have a this Fee Calculator which I've added a Stopwatch to see how much time it will takes to perform:
public class SyncPricingService
{
public int CalculateFees()
{
var watch = Stopwatch.StartNew();
var ticketFee = GetTicketPrice();
var insuranceFee = GetInsurancePrice();
var vatFee = CalculateVat();
var adminFee = CalculateAdminFee();
var fees = new[] { ticketFee, insuranceFee, vatFee, adminFee };
watch.Stop();
Console.WriteLine($"Total time <CalculateFees>: {watch.ElapsedMilliseconds}ms");
return fees.Sum();
}
}
Later we will calculate the fee with sync approach by simply using syncPricingService.CalculateFees();
Here is the flow which will take 8.5 second:
▶️ Runnable sample: Sync Fee Calculator
Async Solution:
again we have multple functions for calculating fees:
private async Task<int> GetTicketPriceAsync()
{
Console.WriteLine($" getting Ticket Price at {DateTime.Now}");
await Task.Delay( TimeSpan.FromSeconds(0.5));
return 20;
}
private async Task<int> GetInsurancePriceAsync()
{
Console.WriteLine($" getting Insurance Price at {DateTime.Now}");
await Task.Delay( TimeSpan.FromSeconds(1));
return 5;
}
private async Task<int> CalculateVatAsync()
{
Console.WriteLine($" Calculating Vat at {DateTime.Now}");
await Task.Delay( TimeSpan.FromSeconds(5));
return 1;
}
private async Task<int> CalculateAdminFeeAsync()
{
Console.WriteLine($" Calculating Admin fee at {DateTime.Now}");
await Task.Delay( TimeSpan.FromSeconds(2));
return 2;
}
and here we have this Fee Calculator:
public class AsyncPricingService
{
public async Task<int> CalculateFeesAsync()
{
var watch = Stopwatch.StartNew();
var ticketFeeTask = GetTicketPriceAsync();
var insuranceFeeFeeTask = GetInsurancePriceAsync();
var vatFeeTask = CalculateVatAsync();
var adminFeeTask = CalculateAdminFeeAsync();
var fees = await Task.WhenAll( ticketFeeTask, insuranceFeeTask, vatFeeTask, adminFeeTask );
watch.Stop();
Console.WriteLine($"Total time <CalculateFeesAsync>: {watch.ElapsedMilliseconds}ms");
return fees.Sum();
}
}
Later we can simply calculate the fee with async approach by calling await asyncPricingService.CalculateFeesAsync();
Here is the flow which will take 5 second:
▶️ Runnable sample: Async Fee Calculator



Top comments (0)