Asynchronous Programming in C#: async/await, Tasks & TPL

1. Asynchronous Programming in C#

Q: What is asynchronous programming in C#?

Asynchronous programming allows tasks to run concurrently without blocking the main thread, improving responsiveness and performance for I/O-bound (e.g., file operations, network calls) or CPU-bound tasks. In C#, this is achieved using the async and await keywords, built on the Task class and the Task Parallel Library (TPL).

Q: Why is asynchronous programming important?

Q: How does asynchronous programming in C# differ from C/C++?

2. async and await Keywords

Q: What are the async and await keywords in C#?

Syntax:

async Task MethodNameAsync() {
    await Task.Delay(1000); // Non-blocking wait
}

Q: What are the rules for using async and await?

Q: Can you give an example of async and await in C#?

using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace AsyncAwait
{
    class Program
    {
        static async Task Main(string[] args) // Note: async Main
        {
            try
            {
                Console.WriteLine("Starting async operation...");
                string result = await DownloadContentAsync("https://example.com");
                Console.WriteLine($"Content length: {result.Length}");
            }
            catch (HttpRequestException ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }

        static async Task<string> DownloadContentAsync(string url)
        {
            using (HttpClient client = new HttpClient())
            {
                // Simulate delay for demonstration
                await Task.Delay(1000);
                string content = await client.GetStringAsync(url);
                return content;
            }
        }
    }
}

Output (example):

Starting async operation...
Content length: 1256

3. Tasks and Task Parallel Library (TPL)

Q: What is a Task in C#?

A Task (in System.Threading.Tasks) represents an asynchronous operation that may return a value (Task<T>) or no value (Task). It is the core of C#'s asynchronous programming model, used with async/await or TPL methods.

Q: What is the Task Parallel Library (TPL)?

The TPL is a .NET library (System.Threading.Tasks) that simplifies parallel and asynchronous programming. It provides:

Q: How do you use tasks in C#?

Tasks can be:

Q: Can you give an example of tasks and TPL in C#?

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

namespace TasksTPL
{
    class Program
    {
        static async Task Main(string[] args)
        {
            try
            {
                // Task: Run a single async operation
                Task<int> task1 = Task.Run(() => ComputeSum(1, 100));
                Console.WriteLine($"Task result: {await task1}");

                // Parallel: Run multiple tasks concurrently
                await Task.Run(() => Parallel.Invoke(
                    () => Console.WriteLine("Parallel task 1"),
                    () => Console.WriteLine("Parallel task 2")
                ));

                // Task.WhenAll: Run multiple tasks and wait for all
                Task<string>[] tasks = new[]
                {
                    ProcessDataAsync("Data1", 1000),
                    ProcessDataAsync("Data2", 1500)
                };
                string[] results = await Task.WhenAll(tasks);
                Console.WriteLine("Task.WhenAll results:");
                foreach (var result in results)
                {
                    Console.WriteLine(result);
                }

                // Cancellation
                using (var cts = new CancellationTokenSource(2000)) // Cancel after 2s
                {
                    try
                    {
                        await LongRunningTaskAsync(cts.Token);
                    }
                    catch (OperationCanceledException)
                    {
                        Console.WriteLine("Task was cancelled.");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }

        static int ComputeSum(int start, int end)
        {
            int sum = 0;
            for (int i = start; i <= end; i++)
            {
                sum += i;
            }
            return sum;
        }

        static async Task<string> ProcessDataAsync(string name, int delay)
        {
            await Task.Delay(delay);
            return $"Processed {name}";
        }

        static async Task LongRunningTaskAsync(CancellationToken token)
        {
            for (int i = 0; i < 5; i++)
            {
                token.ThrowIfCancellationRequested();
                Console.WriteLine($"Step {i + 1}");
                await Task.Delay(1000, token);
            }
        }
    }
}

Output (example):

Task result: 5050
Parallel task 1
Parallel task 2
Task.WhenAll results:
Processed Data1
Processed Data2
Step 1
Step 2
Task was cancelled.

Note: The output may vary slightly due to parallel execution order.

Q: How do tasks and TPL differ from C/C++?

4. Common Mistakes & Best Practices

Q: Common mistakes?

Async/Await:

Tasks/TPL:

Q: Best practices?

Async/Await:

Tasks/TPL:

General: