📖 Scenario: You are working on a program that reads numbers from a list and processes them. You want to understand the difference between reading data using a normal stream (synchronous) and an async stream (asynchronous).
🎯 Goal: Build a simple C# program that first reads numbers from a list using a normal IEnumerable<int> stream, then reads numbers asynchronously using an IAsyncEnumerable<int> stream. You will see how the async stream allows waiting for data asynchronously.
📋 What You'll Learn
Create a list of integers called numbers with values 1, 2, 3, 4, 5.
Create a synchronous method GetNumbers() that returns IEnumerable<int> from the numbers list.
Create an asynchronous method GetNumbersAsync() that returns IAsyncEnumerable<int> and yields numbers with a 500ms delay between each.
Use a foreach loop to print numbers from GetNumbers().
Use an await foreach loop to print numbers from GetNumbersAsync().
Print messages to show when synchronous and asynchronous reading starts and ends.
💡 Why This Matters
🌍 Real World
Reading data from files, databases, or network sources often requires asynchronous streams to avoid blocking the program while waiting for data.
💼 Career
Understanding synchronous vs asynchronous streams is important for writing efficient and responsive C# applications, especially in web development and data processing.
Progress0 / 4 steps
1
Create the list of numbers
Create a list of integers called numbers with the exact values 1, 2, 3, 4, 5.
C Sharp (C#)
Hint
Use List<int> and initialize it with { 1, 2, 3, 4, 5 }.
2
Create synchronous and asynchronous methods
Add a synchronous method GetNumbers() that returns IEnumerable<int> from the numbers list. Also add an asynchronous method GetNumbersAsync() that returns IAsyncEnumerable<int> and yields each number with a 500ms delay using await Task.Delay(500).
C Sharp (C#)
Hint
Use yield return to return each number in GetNumbers(). In GetNumbersAsync(), add await Task.Delay(500) before yielding each number.
3
Print numbers synchronously and asynchronously
In the Main method, first print "Synchronous reading:" then use a foreach loop with variables number to iterate over GetNumbers() and print each number. Then print "Asynchronous reading:" and use an async Task Main() method with await foreach loop over GetNumbersAsync() to print each number.
C Sharp (C#)
Hint
Use Console.WriteLine to print messages. Use foreach for synchronous and await foreach for asynchronous iteration.
4
Run and observe output
Run the program and observe the output. It should first print numbers 1 to 5 immediately under "Synchronous reading:" and then print numbers 1 to 5 with a delay under "Asynchronous reading:".
C Sharp (C#)
Hint
Run the program and check that the synchronous numbers print immediately, then the asynchronous numbers print with delay.
Practice
(1/5)
1. What is the main difference between a Stream and an async stream in C#?
easy
A. A Stream processes data synchronously, while an async stream processes data asynchronously.
B. A Stream can only read data, but an async stream can only write data.
C. A Stream is used for text data, and an async stream is used for binary data.
D. There is no difference; both work the same way.
Solution
Step 1: Understand Stream behavior
A Stream reads or writes data step-by-step synchronously, blocking the thread until data is processed.
Step 2: Understand async stream behavior
An async stream uses IAsyncEnumerable<T> and await foreach to process data asynchronously, allowing other work while waiting for data.
Final Answer:
A Stream processes data synchronously, while an async stream processes data asynchronously. -> Option A
Quick Check:
Sync vs async processing = C [OK]
Hint: Sync streams block; async streams use await foreach [OK]
Common Mistakes:
Thinking async streams are only for writing data
Confusing synchronous with asynchronous processing
Believing streams only handle text or binary exclusively
2. Which of the following is the correct syntax to consume an async stream in C#?
easy
A. foreach (var item in asyncStream) { Console.WriteLine(item); }
B. await foreach (var item in asyncStream) { Console.WriteLine(item); }
C. for await (var item in asyncStream) { Console.WriteLine(item); }
D. async foreach (var item in asyncStream) { Console.WriteLine(item); }
Solution
Step 1: Recall async stream consumption syntax
Async streams require await foreach to asynchronously iterate over IAsyncEnumerable<T>.
Step 2: Check each option
foreach (var item in asyncStream) { Console.WriteLine(item); } uses regular foreach which is invalid for async streams. await foreach (var item in asyncStream) { Console.WriteLine(item); } correctly uses await foreach. for await (var item in asyncStream) { Console.WriteLine(item); } uses invalid syntax for await. async foreach (var item in asyncStream) { Console.WriteLine(item); } uses invalid keyword order async foreach.
Final Answer:
await foreach (var item in asyncStream) { Console.WriteLine(item); } -> Option B
Quick Check:
Async stream needs await foreach = A [OK]
Hint: Use 'await foreach' to read async streams correctly [OK]
Common Mistakes:
Using regular foreach with async streams
Swapping 'async' and 'await' keywords incorrectly
Trying 'for await' which is invalid in C#
3. Consider this code snippet:
async IAsyncEnumerable<int> GetNumbersAsync()
{
for (int i = 1; i <= 3; i++)
{
await Task.Delay(100);
yield return i;
}
}
static async Task Main()
{
await foreach (var num in GetNumbersAsync())
{
Console.Write(num + " ");
}
}
What will be the output when this program runs?
medium
A. Task not awaited error
B. 123
C. 1 2 3
D. No output
Solution
Step 1: Understand async stream generation
The method yields numbers 1 to 3 with a 100ms delay between each, simulating asynchronous data arrival.
Step 2: Understand async stream consumption
The await foreach prints each number followed by a space as they arrive asynchronously.
Final Answer:
1 2 3 -> Option C
Quick Check:
Async yield with await foreach prints spaced numbers = A [OK]