C# Task
By FoxLearn 12/14/2024 2:11:12 PM 128
Concurrent programming is used for I/O-bound tasks (e.g., network requests, database access, or file operations) and CPU-bound tasks (e.g., heavy computations like math calculations or graphics processing). I/O-bound tasks focus on efficient waiting, while CPU-bound tasks emphasize maximizing processor usage.
Asynchronous operations are ideal for I/O-bound tasks, while parallel operations are better suited for CPU-bound tasks. In C#, the Task
class supports both asynchronous and parallel operations, offering flexibility not commonly found in other languages.
Task
represents a concurrent operation, while Task<TResult>
represents a concurrent operation that returns a value. Task.Run
executes CPU-bound code concurrently, queuing the work on the ThreadPool
and returning a Task
or Task<TResult>
handle.
C# Task.Run
Task.Run
offloads a task to a separate thread, making it suitable for CPU-bound operations.
using System; using System.Threading; using System.Threading.Tasks; class Program { static void Main(string[] args) { Console.WriteLine($"Main thread {GetThreadId()} started"); Task.Run(() => { Console.WriteLine($"Worker thread {GetThreadId()} started"); Thread.Sleep(2000); // Simulate some work Console.WriteLine($"Worker thread {GetThreadId()} finished"); }); Console.WriteLine($"Main thread {GetThreadId()} continues execution"); Console.ReadLine(); } static int GetThreadId() { return Thread.CurrentThread.ManagedThreadId; } }
Output:
Main thread 1 started Main thread 1 continues execution Worker thread 3 started Worker thread 3 finished
The main thread completes before the generated task. To ensure the task finishes before the program exits, Console.ReadLine
is used to wait for user input.
C# Task.Delay
Task.Delay
creates a task that completes after a specified time delay.
using System; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { Console.WriteLine("Task started."); // Task.Delay creates a delay of 3 seconds await Task.Delay(3000); Console.WriteLine("Task completed after 3 seconds."); Console.ReadLine(); } }
Output:
Task started. Task completed after 3 seconds.
Task.Delay
creates a task that sleeps for a specified time (e.g., 3 seconds). The await
operator waits for the task to complete, blocking further execution of the main program until the task finishes.
When using the await
operator inside the Main
method, the method must be marked with the async
modifier.
C# Task.WaitAll
The Task.WaitAll
method waits for all of the provided tasks to complete execution.
using System; using System.Threading.Tasks; class Program { static void Main(string[] args) { // Creating multiple tasks Task task1 = Task.Run(() => { Console.WriteLine("Task 1 started."); Task.Delay(2000).Wait(); // Simulate work Console.WriteLine("Task 1 completed."); }); Task task2 = Task.Run(() => { Console.WriteLine("Task 2 started."); Task.Delay(1000).Wait(); // Simulate work Console.WriteLine("Task 2 completed."); }); // Wait for all tasks to complete Task.WaitAll(task1, task2); Console.WriteLine("All tasks have completed."); } }
Output:
Task 1 started. Task 2 started. Task 2 completed. Task 1 completed. All tasks have completed.
The Task.WaitAll
method ensures that the main program waits for both task1
and task2
to complete before continuing.
C# Task.ContinueWith
Task.ContinueWith
creates a continuation that executes asynchronously when the target Task<TResult>
completes.
using System; using System.Threading.Tasks; class Program { static void Main(string[] args) { Task<int> task1 = Task.Run(() => { Console.WriteLine("Task 1 started."); Task.Delay(2000).Wait(); // Simulate some work Console.WriteLine("Task 1 completed."); return 42; // Return a value }); task1.ContinueWith((previousTask) => { Console.WriteLine($"Task 1 result: {previousTask.Result}"); Console.WriteLine("Task 2 started."); Task.Delay(1000).Wait(); // Simulate some work Console.WriteLine("Task 2 completed."); }); Console.WriteLine("Main program continues execution."); Console.ReadLine(); } }
Output:
Main program continues execution. Task 1 started. Task 1 completed. Task 1 result: 42 Task 2 started. Task 2 completed.
C# mulitple async requests
The HttpClient
class is used to send HTTP requests and receive HTTP responses from a specified resource.
using System; using System.Net.Http; using System.Threading.Tasks; internal class Program { static async Task Main(string[] args) { // Define the URLs to request string[] urls = new string[] { "https://jsonplaceholder.typicode.com/posts/1", "https://jsonplaceholder.typicode.com/posts/2", "https://jsonplaceholder.typicode.com/posts/3" }; // Create an HttpClient instance using (HttpClient client = new HttpClient()) { // Create an array of tasks for the requests Task<string>[] tasks = new Task<string>[urls.Length]; // Initiate asynchronous requests for (int i = 0; i < urls.Length; i++) { tasks[i] = FetchDataAsync(client, urls[i]); } // Wait for all tasks to complete and get their results string[] results = await Task.WhenAll(tasks); // Output the results for (int i = 0; i < results.Length; i++) { Console.WriteLine($"Response from {urls[i]}: {results[i].Substring(0, 100)}..."); // Display first 100 chars } } } // Asynchronous method to fetch data from a URL static async Task<string> FetchDataAsync(HttpClient client, string url) { Console.WriteLine($"Requesting: {url}"); var response = await client.GetStringAsync(url); return response; } }
Output:
Requesting: https://jsonplaceholder.typicode.com/posts/1 Requesting: https://jsonplaceholder.typicode.com/posts/2 Requesting: https://jsonplaceholder.typicode.com/posts/3 Response from https://jsonplaceholder.typicode.com/posts/1: { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio... Response from https://jsonplaceholder.typicode.com/posts/2: { "userId": 1, "id": 2, "title": "qui est esse", "body": "est rerum tempore vitae\nsequi sin... Response from https://jsonplaceholder.typicode.com/posts/3: { "userId": 1, "id": 3, "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut"...
Multiple asynchronous HTTP requests are made by initiating them in parallel with Task[]
and await Task.WhenAll()
. The Task.WhenAll()
method waits for all the tasks (requests) to complete and returns their results.
- How to use JsonConverterFactory in C#
- How to serialize non-public properties using System.Text.Json
- The JSON value could not be converted to System.DateTime
- Try/finally with no catch block in C#
- Parsing a DateTime from a string in C#
- Async/Await with a Func delegate in C#
- How to batch read with Threading.ChannelReader in C#
- How to ignore JSON deserialization errors in C#