AsyncAwaitScenarioQuestions

C# Question Bank

Async & Await | 10 Scenario Questions (5 Moderate + 5 Complex) — Questions Only

Instruction: Students should implement ONLY the methods marked with // ✅ TODO.
Each question includes a complex sample input (spaces, quotes, unicode α/β, emoji ✅, special chars like @ # % !, currency ₹). Replace it with your own as required.
Do not add answers in this page.
Moderate: 5 Complex: 5 Coverage: WhenAll, WhenAny, Timeout, Progress, Cancellation, SemaphoreSlim, Async Streams, Backoff Retry, Batch Report
1

Async Text Sanitizer — Read, Normalize, Save

AsyncawaitFile IO (simulated)StringModerate

Scenario: A support chat export is copied as multi-line text with extra spaces and special symbols. You must sanitize it asynchronously and return a single normalized string. What to implement: - ChatSanitizer.NormalizeAsync(string rawText) Rules: - Use await Task.Yield() to simulate asynchronous work per line - Trim each line, remove empty lines - Replace multiple spaces with single space - Keep unicode and emoji - Return joined lines with '\n' ✅ Student task: Implement ONLY the TODO method.

✅ Sample input intentionally contains spaces, quotes, unicode α/β, emoji ✅, special chars like @ # % !, and currency ₹.
Async/Await scenario (students implement ONLY TODO methods) Ctrl+C
using System;                                   // basic types
using System.Linq;                                // Split / LINQ
using System.Text.RegularExpressions;             // regex for spaces
using System.Threading.Tasks;                     // Task / async

namespace ItTechGenie.M1.AsyncAwait.Q1
{
    public static class ChatSanitizer
    {
        // ✅ TODO: Student must implement only this method
        public static async Task<string> NormalizeAsync(string rawText)
        {
            // TODO:
            // - validate rawText not null
            // - split by newlines
            // - await Task.Yield() per line (simulate async)
            // - trim, skip empty
            // - replace multiple spaces with single space
            // - join using "\n"
            throw new NotImplementedException();
        }
    }

    internal class Program
    {
        static async Task Main()
        {
            var raw = "  Ticket: #A-901  \n User :  Sana @ Chennai ✅   \n\n Issue:  Login  failed!!!   \n Note :  Reset   password  @  10:30 PM  ";
            var normalized = await ChatSanitizer.NormalizeAsync(raw);
            Console.WriteLine(normalized);
        }
    }
}
2

Async Price Fetcher — Task.WhenAll

AsyncTask.WhenAllAggregationModerate

Scenario: Fetch prices for multiple SKUs asynchronously (simulate API calls). Return a dictionary of SKU -> price. What to implement: - PriceClient.FetchPricesAsync(string[] skus) Rules: - For each SKU, call SimulateFetchAsync(sku) - Use Task.WhenAll to run in parallel - Preserve the same count as input SKUs - Validate SKU not null/empty after trim ✅ Student task: Implement ONLY the TODO method.

✅ Sample input intentionally contains spaces, quotes, unicode α/β, emoji ✅, special chars like @ # % !, and currency ₹.
Async/Await scenario (students implement ONLY TODO methods) Ctrl+C
using System;                                   // Console
using System.Collections.Generic;                  // Dictionary
using System.Threading.Tasks;                      // Task
using System.Linq;                                // LINQ

namespace ItTechGenie.M1.AsyncAwait.Q2
{
    public static class PriceClient
    {
        // Simulated async API call (already provided)
        private static async Task<decimal> SimulateFetchAsync(string sku)
        {
            await Task.Delay(50);                  // simulate network delay
            return sku.Length * 111.11m;           // deterministic fake price
        }

        // ✅ TODO: Student must implement only this method
        public static async Task<Dictionary<string, decimal>> FetchPricesAsync(string[] skus)
        {
            // TODO:
            // - validate array
            // - trim each sku; throw for empty
            // - create tasks for SimulateFetchAsync
            // - await Task.WhenAll
            // - return dictionary sku->price
            throw new NotImplementedException();
        }
    }

    internal class Program
    {
        static async Task Main()
        {
            var skus = new[] { " SKU-α12 ", "SKU-β77", " SKU-!@# " };
            var prices = await PriceClient.FetchPricesAsync(skus);

            foreach (var kv in prices)
                Console.WriteLine($"{kv.Key} => ₹ {kv.Value}");
        }
    }
}
3

Async Timeout Wrapper — Task.WhenAny

AsyncTimeoutTask.WhenAnyModerate

Scenario: Wrap any async operation with a timeout. If operation does not finish in time, throw TimeoutException. What to implement: - TimeoutUtil.WithTimeoutAsync<T>(Task<T> work, int timeoutMs) Rules: - timeoutMs must be > 0 - If work completes first -> return its result - If timeout completes first -> throw TimeoutException ✅ Student task: Implement ONLY the TODO method.

✅ Sample input intentionally contains spaces, quotes, unicode α/β, emoji ✅, special chars like @ # % !, and currency ₹.
Async/Await scenario (students implement ONLY TODO methods) Ctrl+C
using System;                                   // TimeoutException
using System.Threading.Tasks;                      // Task

namespace ItTechGenie.M1.AsyncAwait.Q3
{
    public static class TimeoutUtil
    {
        // ✅ TODO: Student must implement only this method
        public static async Task<T> WithTimeoutAsync<T>(Task<T> work, int timeoutMs)
        {
            // TODO:
            // - validate inputs
            // - create timeout Task.Delay(timeoutMs)
            // - await Task.WhenAny
            // - if timeout wins => throw TimeoutException
            // - else return await work (propagate exceptions)
            throw new NotImplementedException();
        }
    }

    internal class Program
    {
        static async Task Main()
        {
            Task<string> work = Task.Run(async () =>
            {
                await Task.Delay(100);             // simulate work
                return "RESULT ✅";
            });

            var result = await TimeoutUtil.WithTimeoutAsync(work, 200);
            Console.WriteLine(result);
        }
    }
}
4

Async JSON Parser — Exception Propagation

AsyncExceptionsParsingModerate

Scenario: Parse a JSON-like string asynchronously. If required keys are missing, throw FormatException. What to implement: - PayloadParser.ParseOrderIdAsync(string payload) Rules: - payload must contain "orderId":"..." (quotes included) - Return extracted orderId string (trim) - Use await Task.Yield() once to simulate async parsing ✅ Student task: Implement ONLY the TODO method.

✅ Sample input intentionally contains spaces, quotes, unicode α/β, emoji ✅, special chars like @ # % !, and currency ₹.
Async/Await scenario (students implement ONLY TODO methods) Ctrl+C
using System;                                   // FormatException
using System.Threading.Tasks;                      // Task

namespace ItTechGenie.M1.AsyncAwait.Q4
{
    public static class PayloadParser
    {
        // ✅ TODO: Student must implement only this method
        public static async Task<string> ParseOrderIdAsync(string payload)
        {
            // TODO:
            // - validate payload not null/empty
            // - await Task.Yield()
            // - find "orderId"
            // - extract value between quotes
            // - trim and return
            // - throw FormatException if missing/invalid
            throw new NotImplementedException();
        }
    }

    internal class Program
    {
        static async Task Main()
        {
            var payload = "{ \"orderId\": \" O-90 01 \" , \"note\": \"paid ₹ 1,999.25 ✅\" }";
            var id = await PayloadParser.ParseOrderIdAsync(payload);
            Console.WriteLine($"OrderId => [{id}]");
        }
    }
}
5

Async Progress Reporter — IProgress<T>

AsyncIProgressawaitConsoleModerate

Scenario: A batch job processes N records asynchronously and reports progress. What to implement: - BatchJob.ProcessAsync(string[] records, IProgress<int> progress) Rules: - For each record: await Task.Delay(20) - Report progress as percentage (0..100) after each record - Trim record; ignore empty records ✅ Student task: Implement ONLY the TODO method.

✅ Sample input intentionally contains spaces, quotes, unicode α/β, emoji ✅, special chars like @ # % !, and currency ₹.
Async/Await scenario (students implement ONLY TODO methods) Ctrl+C
using System;                                   // Console
using System.Threading.Tasks;                      // Task
using System.Linq;                                // Where
using System.Collections.Generic;                  // List

namespace ItTechGenie.M1.AsyncAwait.Q5
{
    public static class BatchJob
    {
        // ✅ TODO: Student must implement only this method
        public static async Task<int> ProcessAsync(string[] records, IProgress<int> progress)
        {
            // TODO:
            // - validate inputs
            // - process non-empty trimmed records
            // - await delay per record
            // - report percentage via progress.Report(...)
            // - return count of processed records
            throw new NotImplementedException();
        }
    }

    internal class Program
    {
        static async Task Main()
        {
            var records = new[] { "  emp: Ravi  | dept: IT  ", "  emp: Sana @ Chennai ✅ | dept: HR ", "   ", "  emp: Arjun | dept: QA#1 " };

            var progress = new Progress<int>(p => Console.WriteLine($"Progress: {p}%")); // progress callback
            var count = await BatchJob.ProcessAsync(records, progress);

            Console.WriteLine($"Processed: {count}");
        }
    }
}
6

CancellationToken — Cancel Long Running Pipeline

AsyncCancellationTokenawaitRobustnessComplex

Scenario: Process events until cancellation is requested. Each event takes time (simulated IO). What to implement: - EventPipeline.RunAsync(string[] events, CancellationToken token) Rules: - For each event: token.ThrowIfCancellationRequested() then await Task.Delay(40, token) - Return number of processed events before cancellation - Ignore empty events after trim ✅ Student task: Implement ONLY the TODO method.

✅ Sample input intentionally contains spaces, quotes, unicode α/β, emoji ✅, special chars like @ # % !, and currency ₹.
Async/Await scenario (students implement ONLY TODO methods) Ctrl+C
using System;                                   // Console
using System.Threading;                            // CancellationToken
using System.Threading.Tasks;                      // Task
using System.Linq;                                // LINQ

namespace ItTechGenie.M1.AsyncAwait.Q6
{
    public static class EventPipeline
    {
        // ✅ TODO: Student must implement only this method
        public static async Task<int> RunAsync(string[] events, CancellationToken token)
        {
            // TODO:
            // - validate events
            // - iterate trimmed non-empty events
            // - throw if cancellation requested
            // - await Task.Delay(40, token) per event
            // - return processed count
            throw new NotImplementedException();
        }
    }

    internal class Program
    {
        static async Task Main()
        {
            var events = new[] { " EVT#1 | Login | user='Sana @ Chennai' ", " EVT#2 | Create | sku='SKU-β77' ✅ ", "   ", " EVT#3 | Pay | amt='₹ 1,999.25' " };

            using var cts = new CancellationTokenSource();
            cts.CancelAfter(90);                    // cancel quickly

            try
            {
                var processed = await EventPipeline.RunAsync(events, cts.Token);
                Console.WriteLine($"Processed={processed}");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("Cancelled ✅");
            }
        }
    }
}
7

SemaphoreSlim Throttling — Limit Concurrency

AsyncSemaphoreSlimTask.WhenAllThrottlingComplex

Scenario: Upload multiple files, but allow only N uploads at a time. What to implement: - Uploader.UploadAllAsync(string[] fileNames, int maxParallel) Rules: - Use SemaphoreSlim(maxParallel) - For each file: await semaphore.WaitAsync(); finally Release() - Use Task.WhenAll - Return list of results "OK:<file>" for each successful upload ✅ Student task: Implement ONLY the TODO method.

✅ Sample input intentionally contains spaces, quotes, unicode α/β, emoji ✅, special chars like @ # % !, and currency ₹.
Async/Await scenario (students implement ONLY TODO methods) Ctrl+C
using System;                                   // Console
using System.Collections.Generic;                  // List
using System.Threading;                            // SemaphoreSlim
using System.Threading.Tasks;                      // Task
using System.Linq;                                // LINQ

namespace ItTechGenie.M1.AsyncAwait.Q7
{
    public static class Uploader
    {
        // Simulated upload (already provided)
        private static async Task<string> UploadOneAsync(string file)
        {
            await Task.Delay(60);                  // simulate network
            return $"OK:{file.Trim()}";            // deterministic result
        }

        // ✅ TODO: Student must implement only this method
        public static async Task<List<string>> UploadAllAsync(string[] fileNames, int maxParallel)
        {
            // TODO:
            // - validate inputs
            // - create SemaphoreSlim(maxParallel)
            // - create one Task per file that waits, uploads, releases
            // - await Task.WhenAll
            // - return results list
            throw new NotImplementedException();
        }
    }

    internal class Program
    {
        static async Task Main()
        {
            var files = new[] { " report 2026-02-18 (final) ✅.txt ", " invoice#₹1999.25.csv ", " photo @ beach 😄.png " };
            var results = await Uploader.UploadAllAsync(files, maxParallel: 2);
            results.ForEach(Console.WriteLine);
        }
    }
}
8

Async Enumerable Stream — Yield Results

Async StreamsIAsyncEnumerableawait foreachComplex

Scenario: Stream parsed tokens from an input text asynchronously. Input contains separators like ',', ';', '|', and multiple spaces. What to implement: - TokenStream.ReadTokensAsync(string text) Rules: - Split by separators: ',', ';', '|' - Trim each token; ignore empties - For each token: await Task.Delay(10) then yield return token - Use IAsyncEnumerable<string> ✅ Student task: Implement ONLY the TODO method.

✅ Sample input intentionally contains spaces, quotes, unicode α/β, emoji ✅, special chars like @ # % !, and currency ₹.
Async/Await scenario (students implement ONLY TODO methods) Ctrl+C
using System;                                   // String
using System.Collections.Generic;                  // IAsyncEnumerable
using System.Threading.Tasks;                      // Task
using System.Runtime.CompilerServices;             // EnumeratorCancellation
using System.Threading;                            // CancellationToken

namespace ItTechGenie.M1.AsyncAwait.Q8
{
    public static class TokenStream
    {
        // ✅ TODO: Student must implement only this method
        public static async IAsyncEnumerable<string> ReadTokensAsync(
            string text,
            [EnumeratorCancellation] CancellationToken token = default)
        {
            // TODO:
            // - validate text
            // - split by ',', ';', '|'
            // - foreach token: token.ThrowIfCancellationRequested()
            // - await Task.Delay(10, token)
            // - yield return trimmed token when not empty
            throw new NotImplementedException();
        }
    }

    internal class Program
    {
        static async Task Main()
        {
            var text = "  SKU-α12 ,  Laptop Stand ; ₹ 1299.50 |  user='Sana @ Chennai ✅'  |  ";

            await foreach (var t in TokenStream.ReadTokensAsync(text))
                Console.WriteLine($"TOKEN => [{t}]");
        }
    }
}
9

Async Retry with Exponential Backoff

AsyncRetryBackoffExceptionsComplex

Scenario: Call an async operation that may fail transiently. Retry on TimeoutException using exponential backoff. What to implement: - BackoffRetry.RunAsync(Func<Task<string>> action, int maxRetries, int baseDelayMs) Rules: - maxRetries = retries AFTER first attempt - On TimeoutException: delay baseDelayMs * 2^attemptIndex (attemptIndex starts at 0 for first retry) - On non-timeout exception: rethrow immediately - Return result if success ✅ Student task: Implement ONLY the TODO method.

✅ Sample input intentionally contains spaces, quotes, unicode α/β, emoji ✅, special chars like @ # % !, and currency ₹.
Async/Await scenario (students implement ONLY TODO methods) Ctrl+C
using System;                                   // Func
using System.Threading.Tasks;                      // Task

namespace ItTechGenie.M1.AsyncAwait.Q9
{
    public static class BackoffRetry
    {
        // ✅ TODO: Student must implement only this method
        public static async Task<string> RunAsync(Func<Task<string>> action, int maxRetries, int baseDelayMs)
        {
            // TODO:
            // - validate inputs
            // - try, catch TimeoutException => delay exponential and retry
            // - non-timeout => throw
            // - after exhausting => throw last TimeoutException
            throw new NotImplementedException();
        }
    }

    internal class Program
    {
        static async Task Main()
        {
            int attempts = 0;

            async Task<string> Action()
            {
                attempts++;
                await Task.Delay(10);
                if (attempts <= 2) throw new TimeoutException("timeout");
                return "PAID ✅";
            }

            var result = await BackoffRetry.RunAsync(Action, maxRetries: 3, baseDelayMs: 50);
            Console.WriteLine(result);
        }
    }
}
10

Async Batch with Partial Failures — Aggregate Results

AsyncTask.WhenAllError HandlingResult ModelComplex

Scenario: Process N API calls concurrently. Some calls fail; you must return a report that contains: - SuccessCount - FailureCount - FailedKeys list (preserve original key text) What to implement: - BatchRunner.RunAsync(string[] keys) Rules: - For each key: call SimulateCallAsync(key) - Use Task.WhenAll but handle per-task exceptions - Do NOT crash the entire batch on one failure - Return BatchReport object ✅ Student task: Implement ONLY the TODO method.

✅ Sample input intentionally contains spaces, quotes, unicode α/β, emoji ✅, special chars like @ # % !, and currency ₹.
Async/Await scenario (students implement ONLY TODO methods) Ctrl+C
using System;                                   // Console
using System.Collections.Generic;                  // List
using System.Threading.Tasks;                      // Task
using System.Linq;                                // LINQ

namespace ItTechGenie.M1.AsyncAwait.Q10
{
    public record BatchReport(int SuccessCount, int FailureCount, List<string> FailedKeys);

    public static class BatchRunner
    {
        // Simulated call: fails if key trimmed is empty or contains "   "
        private static async Task<string> SimulateCallAsync(string key)
        {
            await Task.Delay(40);
            var k = (key ?? "").Trim();
            if (string.IsNullOrWhiteSpace(k)) throw new ArgumentException("Key empty");
            return "OK:" + k;
        }

        // ✅ TODO: Student must implement only this method
        public static async Task<BatchReport> RunAsync(string[] keys)
        {
            // TODO:
            // - validate keys array
            // - start tasks for each key
            // - await all in a way that doesn't crash whole batch
            // - count successes/failures and collect failed keys (original input)
            throw new NotImplementedException();
        }
    }

    internal class Program
    {
        static async Task Main()
        {
            var keys = new[] { " user:Sana @ Chennai ✅ ", " user:Ravi#QA ", " user:   ", " user:Arjun|Ops " };
            var report = await BatchRunner.RunAsync(keys);

            Console.WriteLine($"Success={report.SuccessCount}, Fail={report.FailureCount}");
            Console.WriteLine("Failed Keys:");
            report.FailedKeys.ForEach(Console.WriteLine);
        }
    }
}