Interview

15 Async Await C# Interview Questions and Answers

Prepare for your C# interview with this guide on async and await. Enhance your understanding of asynchronous programming concepts and improve your coding skills.

Async and await are essential features in C# that enable developers to write asynchronous code more efficiently and intuitively. These keywords simplify the process of managing asynchronous operations, making code easier to read and maintain. Asynchronous programming is crucial for improving application performance, especially in scenarios involving I/O-bound operations, such as web requests and file handling.

This article provides a curated selection of interview questions focused on async and await in C#. Reviewing these questions will help you deepen your understanding of asynchronous programming concepts and prepare you to discuss them confidently in technical interviews.

Async Await C# Interview Questions and Answers

1. What is the purpose of async and await keywords in C#?

The async and await keywords in C# enable asynchronous programming, allowing for non-blocking operations. The async keyword defines a method as asynchronous, while await pauses its execution until the awaited task completes without blocking the main thread.

Example:

public async Task<string> FetchDataAsync()
{
    HttpClient client = new HttpClient();
    string result = await client.GetStringAsync("https://example.com");
    return result;
}

public async Task MainMethod()
{
    string data = await FetchDataAsync();
    Console.WriteLine(data);
}

In this example, FetchDataAsync fetches data from a URL asynchronously. The await keyword waits for GetStringAsync to complete. MainMethod also uses await to wait for FetchDataAsync before printing the result.

2. Write a simple example of an async method that reads a file asynchronously.

Here is a simple example of an async method that reads a file asynchronously:

using System;
using System.IO;
using System.Threading.Tasks;

public class FileReader
{
    public async Task<string> ReadFileAsync(string filePath)
    {
        using (StreamReader reader = new StreamReader(filePath))
        {
            return await reader.ReadToEndAsync();
        }
    }
}

public class Program
{
    public static async Task Main(string[] args)
    {
        FileReader fileReader = new FileReader();
        string content = await fileReader.ReadFileAsync("example.txt");
        Console.WriteLine(content);
    }
}

3. Write a method that uses Task.WhenAll to run multiple asynchronous tasks concurrently.

The Task.WhenAll method runs multiple asynchronous tasks concurrently and waits for all to complete. This is useful for executing independent tasks in parallel.

Example:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main(string[] args)
    {
        List<Task> tasks = new List<Task>
        {
            Task1(),
            Task2(),
            Task3()
        };

        await Task.WhenAll(tasks);
        Console.WriteLine("All tasks completed.");
    }

    public static async Task Task1()
    {
        await Task.Delay(1000);
        Console.WriteLine("Task 1 completed.");
    }

    public static async Task Task2()
    {
        await Task.Delay(2000);
        Console.WriteLine("Task 2 completed.");
    }

    public static async Task Task3()
    {
        await Task.Delay(3000);
        Console.WriteLine("Task 3 completed.");
    }
}

4. How can you cancel an ongoing async operation? Provide a code example.

You can cancel an ongoing async operation using a CancellationToken. The CancellationTokenSource class creates and manages the cancellation token.

Example:

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var cts = new CancellationTokenSource();
        var token = cts.Token;

        var task = LongRunningOperationAsync(token);

        cts.CancelAfter(2000);

        try
        {
            await task;
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Operation was canceled.");
        }
    }

    static async Task LongRunningOperationAsync(CancellationToken token)
    {
        for (int i = 0; i < 10; i++)
        {
            token.ThrowIfCancellationRequested();
            Console.WriteLine($"Working... {i}");
            await Task.Delay(1000);
        }
    }
}

5. Write a method that demonstrates the use of ConfigureAwait(false).

ConfigureAwait(false) prevents the continuation from capturing the current synchronization context, which can help avoid deadlocks and improve performance.

Example:

public async Task ExampleMethodAsync()
{
    await Task.Delay(1000).ConfigureAwait(false);
    Console.WriteLine("Operation completed.");
}

6. Explain the concept of deadlock in the context of async/await and how to avoid it.

Deadlock occurs when tasks wait for each other indefinitely. Avoid using blocking calls like Task.Wait() or Task.Result within async methods. Use await instead to allow tasks to complete asynchronously.

Example:

public async Task ExampleMethodAsync()
{
    var result = await Task.Run(() => LongRunningOperation());
}

public int LongRunningOperation()
{
    Thread.Sleep(5000);
    return 42;
}

7. How would you handle progress reporting in an async method?

Progress reporting in an async method can be handled using the IProgress<T> interface, which provides a way to report updates back to the UI thread or another context.

Example:

public async Task ProcessDataAsync(IProgress<int> progress)
{
    for (int i = 0; i <= 100; i++)
    {
        await Task.Delay(100);
        progress?.Report(i);
    }
}

var progress = new Progress<int>(percent => Console.WriteLine($"Progress: {percent}%"));
await ProcessDataAsync(progress);

8. Write a method that performs an asynchronous operation with a timeout.

To implement a timeout for an asynchronous operation, use a CancellationTokenSource to signal a timeout and cancel the operation if it takes too long.

Example:

using System;
using System.Threading;
using System.Threading.Tasks;

public class AsyncOperation
{
    public async Task<string> PerformOperationWithTimeoutAsync(int timeout)
    {
        using (var cts = new CancellationTokenSource())
        {
            cts.CancelAfter(timeout);

            try
            {
                return await Task.Run(async () =>
                {
                    await Task.Delay(5000);
                    return "Operation Completed";
                }, cts.Token);
            }
            catch (OperationCanceledException)
            {
                return "Operation Timed Out";
            }
        }
    }
}

9. What are the performance implications of using async/await in a high-throughput application?

Using async/await allows for non-blocking operations, improving resource use and scalability. However, it introduces overhead due to the state machine generated by the compiler, which can impact performance. Avoid thread pool exhaustion by managing concurrency effectively.

10. How do you test async methods in unit tests?

Testing async methods involves using a unit testing framework that supports asynchronous code, such as MSTest, NUnit, or xUnit. These frameworks allow you to write test methods that return a Task.

Example using xUnit:

public class AsyncMethodTests
{
    [Fact]
    public async Task TestAsyncMethod()
    {
        var service = new MyService();
        var result = await service.MyAsyncMethod();
        Assert.Equal(expectedResult, result);
    }
}

11. Write a method that chains multiple async operations using await.

Chain multiple async operations using await to ensure each operation completes before the next begins.

Example:

public async Task<string> FetchDataAsync()
{
    string data1 = await GetDataFromService1Async();
    string data2 = await GetDataFromService2Async(data1);
    string data3 = await GetDataFromService3Async(data2);
    return data3;
}

public async Task<string> GetDataFromService1Async()
{
    await Task.Delay(1000);
    return "Data from Service 1";
}

public async Task<string> GetDataFromService2Async(string input)
{
    await Task.Delay(1000);
    return input + " + Data from Service 2";
}

public async Task<string> GetDataFromService3Async(string input)
{
    await Task.Delay(1000);
    return input + " + Data from Service 3";
}

12. How would you debug an async method that is not behaving as expected?

Debugging an async method involves using logging, breakpoints, exception handling, and checking task status. Be mindful of using ConfigureAwait(false) to avoid deadlocks.

Example:

public async Task ExampleAsyncMethod()
{
    try
    {
        Console.WriteLine("Starting ExampleAsyncMethod");
        await Task.Delay(1000).ConfigureAwait(false);
        Console.WriteLine("Completed ExampleAsyncMethod");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Exception: {ex.Message}");
    }
}

13. Write a method that handles both synchronous and asynchronous execution paths.

Handle both synchronous and asynchronous execution paths by using async and await keywords, providing a synchronous alternative when needed.

Example:

public class Example
{
    public async Task<string> GetDataAsync(bool isAsync)
    {
        if (isAsync)
        {
            await Task.Delay(1000);
            return "Data from async path";
        }
        else
        {
            System.Threading.Thread.Sleep(1000);
            return "Data from sync path";
        }
    }
}

14. How do you handle async streams using IAsyncEnumerable?

Async streams allow for asynchronous iteration over a collection of data using IAsyncEnumerable<T>. This is useful for non-blocking iteration over I/O-bound operations.

Example:

public async IAsyncEnumerable<int> GenerateNumbersAsync()
{
    for (int i = 0; i < 10; i++)
    {
        await Task.Delay(1000);
        yield return i;
    }
}

public async Task ProcessNumbersAsync()
{
    await foreach (var number in GenerateNumbersAsync())
    {
        Console.WriteLine(number);
    }
}

15. What are some best practices for writing async code?

Best practices for writing async code include using async and await appropriately, avoiding blocking calls, returning Task or Task<T>, using ConfigureAwait(false), handling exceptions, and avoiding async void except for event handlers.

Example:

public async Task<string> FetchDataAsync(string url)
{
    using (HttpClient client = new HttpClient())
    {
        HttpResponseMessage response = await client.GetAsync(url).ConfigureAwait(false);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
    }
}
Previous

25 Entity Framework Interview Questions and Answers

Back to Interview
Next

10 C# API Interview Questions and Answers