Synchronous Execution
Code runs line by line.
Each statement must finish before the next one starts.
If a task takes time (like a network call), the whole program waits.
Example
public string GetDataSync()
{
var client = new HttpClient();
string result = client.GetStringAsync("https://example.com").Result;
Console.WriteLine("Data received");
return result;
}
Flow:
Start method
↓
Wait for GetStringAsync to finish (blocking)
↓
Continue execution
↓
Print "Data received"
Asynchronous Execution
Code runs until it hits an await.
At await, control returns to the caller while the task continues in the background.
The program can do other work instead of waiting.
When the task completes, execution resumes.
Example
public async Task<string> GetDataAsync()
{
var client = new HttpClient();
string result = await client.GetStringAsync("https://example.com");
Console.WriteLine("Data received");
return result;
}
Flow:
Start method
↓
Begin GetStringAsync (non-blocking)
↓
Return control to caller immediately
↓
Caller can do other work
↓
When GetStringAsync finishes → resume
↓
Print "Data received"
Side‑by‑Side Diagram
Synchronous: Asynchronous:
Caller Caller
| |
|--- Call method |--- Call async method
|--- Wait (blocked) |--- Executes until await
|--- Task completes |--- Task runs in background
|--- Continue |--- Caller continues work
|--- Task completes
|--- Method resumes after await
|--- Continue
Key Differences
Synchronous: Blocks the thread until work is done.
Asynchronous: Frees the thread, resumes later when work is complete.
Async is especially useful for I/O‑bound tasks (network, file, DB).