How async execution flows in C Sharp (C#) - Performance & Efficiency
When we use async code, the program does some work now and some later without waiting. We want to see how this affects the total time the program takes.
How does the program's running time grow when using async calls?
Analyze the time complexity of the following code snippet.
async Task ProcessItemsAsync(List<int> items)
{
foreach (var item in items)
{
await Task.Delay(100); // Simulate async work
Console.WriteLine(item);
}
}
This code processes a list of items one by one, waiting asynchronously for 100 milliseconds each time.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The foreach loop runs once for each item in the list.
- How many times: Exactly as many times as there are items (n times).
Each item causes a 100ms wait, so total time grows as more items are added.
| Input Size (n) | Approx. Operations (waits) |
|---|---|
| 10 | 10 waits x 100ms = 1 second |
| 100 | 100 waits x 100ms = 10 seconds |
| 1000 | 1000 waits x 100ms = 100 seconds |
Pattern observation: The total time grows directly with the number of items; doubling items doubles total wait time.
Time Complexity: O(n)
This means the total time grows in a straight line as the number of items increases.
[X] Wrong: "Async means all items run at the same time, so total time stays the same no matter how many items."
[OK] Correct: Here, the code waits for each item one after another, so the waits add up, not run in parallel.
Understanding how async code runs step-by-step helps you explain program speed clearly and shows you know how to write efficient code.
"What if we changed the foreach loop to start all tasks at once and then awaited them together? How would the time complexity change?"
Practice
await keyword do in an async method in C#?Solution
Step 1: Understand the role of
Theawaitawaitkeyword pauses the async method execution until the awaited task finishes, but it does not block the thread, allowing other work to continue.Step 2: Differentiate from blocking
Blocking the thread would freeze the program, butawaitallows the thread to be free for other tasks.Final Answer:
It pauses the method until the awaited task completes without blocking the thread. -> Option CQuick Check:
awaitpauses without blocking [OK]
- Thinking await blocks the thread
- Confusing await with async keyword
- Assuming await cancels tasks
Solution
Step 1: Identify correct async method declaration
The correct syntax places theasynckeyword before the return type:public async void MyMethod().Step 2: Check other options for syntax errors
Options A, B, and D have incorrect keyword order or placement, which causes syntax errors.Final Answer:
public async void MyMethod() { } -> Option AQuick Check:
async keyword before return type [OK]
- Placing async after return type
- Using async as a method modifier incorrectly
- Adding parentheses after async
async Task<int> GetNumberAsync() {
await Task.Delay(100);
return 5;
}
async Task MainAsync() {
var task = GetNumberAsync();
Console.WriteLine("Before await");
int result = await task;
Console.WriteLine($"Result: {result}");
}
MainAsync().Wait();Solution
Step 1: Analyze the order of execution
The method prints "Before await" immediately after starting the async task, then awaits the task completion before printing the result.Step 2: Understand await behavior
Await pauses MainAsync until GetNumberAsync completes, then prints "Result: 5".Final Answer:
Before await\nResult: 5 -> Option BQuick Check:
Print before await, then after task completes [OK]
- Assuming result prints before 'Before await'
- Thinking await blocks main thread
- Expecting no output due to deadlock
async Task<int> CalculateAsync() {
Task.Delay(1000);
return 10;
}Solution
Step 1: Check usage of Task.Delay
The method callsTask.Delay(1000)but does not await it, so the delay runs but the method immediately returns 10.Step 2: Understand effect of missing await
Without await, the delay is ignored in terms of method flow, causing unexpected behavior.Final Answer:
Missing await before Task.Delay, so delay is ignored. -> Option DQuick Check:
Always await async calls to run properly [OK]
- Forgetting await before async calls
- Changing return type unnecessarily
- Thinking Task.Delay is invalid in async
TaskA() and TaskB() concurrently and wait for both to finish before continuing. Which code snippet correctly achieves this?Solution
Step 1: Understand concurrency with async tasks
Runningawait TaskA(); await TaskB();runs tasks sequentially, not concurrently.Step 2: Use Task.WhenAll for parallel execution
await Task.WhenAll(TaskA(), TaskB());starts both tasks concurrently and awaits their completion together.Step 3: Evaluate other options
TaskA().Wait(); TaskB().Wait(); blocks threads synchronously, and D starts tasks but does not await completion.Final Answer:
await Task.WhenAll(TaskA(), TaskB()); -> Option AQuick Check:
Use Task.WhenAll to await multiple tasks concurrently [OK]
- Awaiting tasks one after another (sequential)
- Blocking with Wait() causing deadlocks
- Starting tasks without awaiting completion
Ready to prove it?
Pass the test and this pattern moves unknown
