A set of technologies in .NET for building web applications and web services. Miscellaneous topics that do not fit into specific categories.
Hi @rajesh yadav ,
You were asking about differences between Asynchrony and Parallelism.
Here's a clear explanation of these concepts
Asynchrony vs Parallelism in C# (.NET)
Asynchrony
Asynchronous programming is about releasing the thread while waiting for an operation to complete. It allows other work to be performed in the meantime.
In simple terms:
- You start an operation (like reading a file or calling a web service).
- Instead of waiting for it to finish, your program returns control to the caller or continues doing other work.
- When the operation finishes, your program resumes from where it left off.
Key points:
- Asynchrony does not mean multiple things are running at exactly the same instant—it means your program can overlap waiting time with other work.
- Best for I/O-bound work: database queries, web requests, file operations.
Parallelism
Parallel programming is about using multiple threads (often on multiple processor cores) to execute multiple operations at the same time.
In simple terms:
- The work is split into smaller pieces.
- Those pieces are executed simultaneously on different CPU cores.
Key points:
- Parallelism requires multiple threads actively working at once.
- Best for CPU-bound work: heavy calculations, data transformations, image processing.
Concurrency
Concurrency is the general ability of your application to make progress on multiple operations at once. Asynchrony and parallelism are two different techniques to achieve concurrency. You may use both at different times depending on whether you're waiting for external operations (asynchrony) or running heavy computation (parallelism).
Examples (Console App)
Example A – Asynchrony (I/O-bound)
This example downloads several web pages without blocking the calling thread. The downloads are started together, and while each one is waiting for the network, other downloads can make progress.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace AsyncExample
{
class Program
{
static async Task Main()
{
// Three test endpoints that artificially delay responses:
var urls = new List<string>
{
"https://httpbin.org/delay/2", // 2 second server delay
"https://httpbin.org/delay/3", // 3 second server delay
"https://httpbin.org/delay/1" // 1 second server delay
};
using var client = new HttpClient();
Console.WriteLine("------ Sequential downloads (one after another) ------");
var sw = Stopwatch.StartNew();
await SequentialDownloads(client, urls);
sw.Stop();
Console.WriteLine($"Sequential total time: {sw.Elapsed.TotalSeconds:F2} seconds\n");
Console.WriteLine("------ Concurrent downloads (start all, await all) ------");
sw.Restart();
await ConcurrentDownloads(client, urls);
sw.Stop();
Console.WriteLine($"Concurrent total time: {sw.Elapsed.TotalSeconds:F2} seconds\n");
}
static async Task SequentialDownloads(HttpClient client, List<string> urls)
{
foreach (var url in urls)
{
Console.WriteLine($"[Sequential] Starting: {url} at {DateTime.Now:HH:mm:ss.fff}");
string content = await client.GetStringAsync(url); // waits, does not block caller thread
Console.WriteLine($"[Sequential] Completed: {url} at {DateTime.Now:HH:mm:ss.fff}; Length: {content.Length}");
}
}
static async Task ConcurrentDownloads(HttpClient client, List<string> urls)
{
// Start all downloads without awaiting each one immediately
var tasks = urls.Select(url => DownloadWithLog(client, url)).ToList();
// Wait for all to finish
string[] results = await Task.WhenAll(tasks);
// Print brief summary
for (int i = 0; i < urls.Count; i++)
{
Console.WriteLine($"[Concurrent] {urls[i]} -> {results[i].Length} characters");
}
}
static async Task<string> DownloadWithLog(HttpClient client, string url)
{
Console.WriteLine($"[Concurrent] Starting: {url} at {DateTime.Now:HH:mm:ss.fff}");
string content = await client.GetStringAsync(url);
Console.WriteLine($"[Concurrent] Completed: {url} at {DateTime.Now:HH:mm:ss.fff}");
return content;
}
}
}
What happens here:
- In the sequential run, the total time is roughly the sum of the delays.
- In the concurrent run, total time is roughly the maximum of the delays:
- All downloads start together.
- While one is waiting for network data, another can progress.
- The program doesn’t waste time sitting idle—this is the main benefit of asynchrony.
Example B – Parallelism (CPU-bound)
This example count all prime numbers in a range using Parallel LINQ (PLINQ), which automatically splits the work across available CPU cores.
using System;
using System.Diagnostics;
using System.Linq;
namespace ParallelExample
{
class Program
{
static void Main()
{
// Adjust the range size to make the test fast or heavy on your machine
int rangeSize = 2_500_000; // try 1_000_000, 2_000_000 depending on your CPU
var numbers = Enumerable.Range(2, rangeSize);
Console.WriteLine($"Counting prime numbers in range 2..{rangeSize + 1}");
// Sequential (one core, one after another)
var sw = Stopwatch.StartNew();
int sequentialCount = numbers.Count(IsPrime);
sw.Stop();
Console.WriteLine($"Sequential prime count: {sequentialCount}");
Console.WriteLine($"Sequential elapsed: {sw.Elapsed.TotalSeconds:F2} seconds\n");
// Parallel (use multiple cores if available)
sw.Restart();
int parallelCount = numbers.AsParallel().Count(IsPrime);
sw.Stop();
Console.WriteLine($"Parallel prime count: {parallelCount}");
Console.WriteLine($"Parallel elapsed: {sw.Elapsed.TotalSeconds:F2} seconds\n");
Console.WriteLine("Note: results should match. Parallel run will often be faster on systems with multiple cores.");
}
static bool IsPrime(int n)
{
if (n < 2) return false;
int limit = (int)Math.Sqrt(n);
for (int i = 2; i <= limit; i++)
{
if (n % i == 0) return false;
}
return true;
}
}
}
What happens here:
- The sequential version runs the prime check on each number one after another.
- The parallel version uses a feature that splits the range into parts and evaluates them on multiple threads at the same time, usually reducing elapsed time on multi-core processors:
- The collection is split into chunks.
- Each chunk is processed on a separate CPU core at the same time.
- This reduces total computation time for CPU-heavy tasks.
- For small ranges, the parallel version may not help and could be slower because splitting and scheduling work costs time. For larger ranges the parallel version typically wins.
Choosing approach:
Asynchrony:
- Downloading files from the internet
- Reading large files from disk Parallelism:
- Performing complex mathematical models
- Processing image filters on many images
Additional documentations: These documents can give you better understanding on asynchronous and parallel programming in .NET products:
- Asynchronous programming patterns - .NET | Microsoft Learn: Asynchronous programming patterns, including the modern Task-based Asynchronous Pattern (TAP).
- The Task Asynchronous Programming (TAP) model with async and await" - C# | Microsoft Learn: How async and await in C# simplify asynchronous code, making it easy to write and maintain without blocking
- Task Parallel Library (TPL) - .NET | Microsoft Learn: .NET’s primary framework for implementing parallelism. The TPL provides high-level APIs for concurrently running code and automatically scales to use available processor cores.
Hope you find this helpful, please reach out if you need any clarification