The description of Task's MSDN is as follows:
[The Task class indicates that a single operation does not return a value and is usually executed asynchronously.
Task object is a central idea. Task-based asynchronous mode was first introduced into .NETFramework 4.
Because the Task object executed by the task is usually executed asynchronously on the thread pool thread instead of in a synchronous manner in the main application thread, the Status property can be used and the IsCanceled, IsCompleted, and IsFaulted properties can be used to determine the status of the task.
In most cases, the lambda expression is used to specify the amount of work the task is performed.
For operations that return values, you use the Task class. 】
1. Advantages of Task
ThreadPool has many advantages over Thread, but ThreadPool has some inconvenience in use. for example:
- ThreadPool does not support interactive operations such as cancellation, completion, and failure notification of threads;
- ThreadPool does not support the order of thread execution;
In the past, if developers wanted to implement the above functions, they had to do a lot of extra work. Now, a more powerful concept is provided in FCL: Task. Task thread pool is optimized based on the basis of the task thread pool and provides more APIs. In FCL4.0, Task is obviously better than the traditional way if we want to write multithreaded programs.
Here is a simple task example:
using System; using ; using ; namespace ConsoleApp1 { class Program { static void Main(string[] args) { Task t = new Task(() => { ("The task starts working..."); //Simulate the working process (5000); }); (); ((task) => { ("The task is completed, and the status when it is completed is:"); ("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", , , ); }); (); } } }
2. How to use Task
2.1. Create a task
(I) Method of no return value
Method 1:
var t1 = new Task(() => TaskMethod("Task 1")); (); (t1);//Waiting for all tasks to endNote:Task status: StartPreviously:Created StartAfter that:WaitingToRun
Method 2:
(() => TaskMethod("Task 2"));
Method 3:
(() => TaskMethod("Task 3")); Direct asynchronous method //orvar t3=(() => TaskMethod("Task 3")); (t3);//Waiting for all tasks to end//Task status:StartPreviously:Running StartAfter that:Running
using System; using ; using ; namespace ConsoleApp1 { class Program { static void Main(string[] args) { var t1 = new Task(() => TaskMethod("Task 1")); var t2 = new Task(() => TaskMethod("Task 2")); (); (); (t1, t2); (() => TaskMethod("Task 3")); (() => TaskMethod("Task 4")); // Mark as long-running tasks, the task will not use thread pools, but run in separate threads. (() => TaskMethod("Task 5"), ); #region General usage ("The main thread executes business processing."); //Create a task Task task = new Task(() => { ("Execute asynchronous operations using."); for (int i = 0; i < 10; i++) { (i); } }); //Start the task and arrange to execute the task in the current task queue thread () (); ("The main thread performs other processing"); (); #endregion ((1)); (); } static void TaskMethod(string name) { ("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, , ); } } }
Async/await implementation method:
using System; using ; using ; namespace ConsoleApp1 { class Program { async static void AsyncFunction() { await (1); ("Execute asynchronous operations using."); for (int i = 0; i < 10; i++) { (("AsyncFunction:i={0}", i)); } } public static void Main() { ("The main thread executes business processing."); AsyncFunction(); ("The main thread performs other processing"); for (int i = 0; i < 10; i++) { (("Main:i={0}", i)); } (); } } }
(II) Method with return value
Method 4:
Task<int> task = CreateTask("Task 1"); (); int result = ;
using System; using ; using ; namespace ConsoleApp1 { class Program { static Task<int> CreateTask(string name) { return new Task<int>(() => TaskMethod(name)); } static void Main(string[] args) { TaskMethod("Main Thread Task"); Task<int> task = CreateTask("Task 1"); (); int result = ; ("Task 1 Result is: {0}", result); task = CreateTask("Task 2"); //This task will run in the main thread (); result = ; ("Task 2 Result is: {0}", result); task = CreateTask("Task 3"); (); (); while (!) { (); ((0.5)); } (); result = ; ("Task 3 Result is: {0}", result); #region General usage //Create a task Task<int> getsumtask = new Task<int>(() => Getsum()); //Start the task and arrange to execute the task in the current task queue thread () (); ("The main thread performs other processing"); //Waiting for the completion of the task. (); //Get the execution results of the task ("Task execution results:{0}", ()); #endregion } static int TaskMethod(string name) { ("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, , ); ((2)); return 42; } static int Getsum() { int sum = 0; ("Use Task to perform asynchronous operations."); for (int i = 0; i < 100; i++) { sum += i; } return sum; } } }
Async/await implementation:
using System; using ; namespace ConsoleApp1 { class Program { public static void Main() { var ret1 = AsyncGetsum(); ("The main thread performs other processing"); for (int i = 1; i <= 3; i++) ("Call Main()"); int result = ; //Block the main thread ("Task execution results:{0}", result); } async static Task<int> AsyncGetsum() { await (1); int sum = 0; ("Use Task to perform asynchronous operations."); for (int i = 0; i < 100; i++) { sum += i; } return sum; } } }
2.2. Combination task.ContinueWith
Simple Demo:
using System; using ; namespace ConsoleApp1 { class Program { public static void Main() { //Create a task Task<int> task = new Task<int>(() => { int sum = 0; ("Use Task to perform asynchronous operations."); for (int i = 0; i < 100; i++) { sum += i; } return sum; }); //Start the task and arrange to execute the task in the current task queue thread () (); ("The main thread performs other processing"); //Execute processing when the task is completed. Task cwt = (t => { ("Execution results after the task is completed:{0}", ()); }); (); (); } } }
Serial of tasks:
using System; using ; using ; using ; namespace ConsoleApp1 { class Program { static void Main(string[] args) { ConcurrentStack<int> stack = new ConcurrentStack<int>(); //t1 first serial var t1 = (() => { (1); (2); }); //t2,t3 executes in parallel var t2 = (t => { int result; (out result); ("Task t2 result={0},Thread id {1}", result, ); }); //t2,t3 executes in parallel var t3 = (t => { int result; (out result); ("Task t3 result={0},Thread id {1}", result, ); }); //Waiting for t2 and t3 to complete execution (t2, t3); //t7 serial execution var t4 = (() => { ("The current number of elements in the collection:{0},Thread id {1}", , ); }); (); } } }
Subtask:
using System; using ; namespace ConsoleApp1 { class Program { public static void Main() { Task<string[]> parent = new Task<string[]>(state => { (state); string[] result = new string[2]; //Create and launch subtask new Task(() => { result[0] = "I'm a submission 1."; }, ).Start(); new Task(() => { result[1] = "I'm a Submission 2."; }, ).Start(); return result; }, "I am a parent task and create multiple subtasks during my processing. I will not end the execution after all subtasks are completed."); //Operations performed after task processing is completed (t => { (, r => (r)); }); //Start the parent task (); //Waiting for the task to end Wait can only wait for the parent thread to end, and there is no way to wait until the parent thread's ContinueWith ends //(); (); } } }
Dynamic parallel() The parent task waits for all child tasks to complete before the entire task is considered completed
using System; using ; using ; namespace ConsoleApp1 { class Node { public Node Left { get; set; } public Node Right { get; set; } public string Text { get; set; } } class Program { static Node GetNode() { Node root = new Node { Left = new Node { Left = new Node { Text = "L-L" }, Right = new Node { Text = "L-R" }, Text = "L" }, Right = new Node { Left = new Node { Text = "R-L" }, Right = new Node { Text = "R-R" }, Text = "R" }, Text = "Root" }; return root; } static void Main(string[] args) { Node root = GetNode(); DisplayTree(root); } static void DisplayTree(Node root) { var task = (() => DisplayNode(root), , , ); (); } static void DisplayNode(Node current) { if ( != null) (() => DisplayNode(), , , ); if ( != null) (() => DisplayNode(), , , ); ("The value of the current node is{0};HandledThreadId={1}", , ); } } }
2.3. Cancel the task CancellationTokenSource
using System; using ; using ; namespace ConsoleApp1 { class Program { private static int TaskMethod(string name, int seconds, CancellationToken token) { ("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, , ); for (int i = 0; i < seconds; i++) { ((1)); if () return -1; } return 42 * seconds; } private static void Main(string[] args) { var cts = new CancellationTokenSource(); var longTask = new Task<int>(() => TaskMethod("Task 1", 10, ), ); (); (); (); ("First task has been cancelled before execution"); cts = new CancellationTokenSource(); longTask = new Task<int>(() => TaskMethod("Task 2", 10, ), ); (); for (int i = 0; i < 5; i++) { ((0.5)); (); } (); for (int i = 0; i < 5; i++) { ((0.5)); (); } ("A task has been completed with result {0}.", ); } } }
2.4. Handle exceptions in tasks
Single task:
using System; using ; using ; namespace ConsoleApp1 { class Program { static int TaskMethod(string name, int seconds) { ("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, , ); ((seconds)); throw new Exception("Boom!"); return 42 * seconds; } static void Main(string[] args) { try { Task<int> task = (() => TaskMethod("Task 2", 2)); int result = ().GetResult(); ("Result: {0}", result); } catch (Exception ex) { ("Task 2 Exception caught: {0}", ); } ("----------------------------------------------"); (); } } }
Multiple tasks:
using System; using ; using ; namespace ConsoleApp1 { class Program { static int TaskMethod(string name, int seconds) { ("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, , ); ((seconds)); throw new Exception(("Task {0} Boom!", name)); return 42 * seconds; } public static void Main(string[] args) { try { var t1 = new Task<int>(() => TaskMethod("Task 3", 3)); var t2 = new Task<int>(() => TaskMethod("Task 4", 2)); var complexTask = (t1, t2); var exceptionHandler = (t => ("Result: {0}", ), ); (); (); (t1, t2); } catch (AggregateException ex) { (exception => { (); return true; }); } } } }
async/await method:
using System; using ; using ; namespace ConsoleApp1 { class Program { static async Task ThrowNotImplementedExceptionAsync() { throw new NotImplementedException(); } static async Task ThrowInvalidOperationExceptionAsync() { throw new InvalidOperationException(); } static async Task Normal() { await Fun(); } static Task Fun() { return (() => { for (int i = 1; i <= 10; i++) { ("i={0}", i); (200); } }); } static async Task ObserveOneExceptionAsync() { var task1 = ThrowNotImplementedExceptionAsync(); var task2 = ThrowInvalidOperationExceptionAsync(); var task3 = Normal(); try { //Asynchronous way Task allTasks = (task1, task2, task3); await allTasks; //Synchronous method //(task1, task2, task3); } catch (NotImplementedException ex) { ("Task1 task error!"); } catch (InvalidOperationException ex) { ("Task2 task error!"); } catch (Exception ex) { ("The task error!"); } } public static void Main() { Task task = ObserveOneExceptionAsync(); ("The main thread continues to run..."); (); } } }
2.5. Application
using System; using ; using ; using ; namespace ConsoleApp1 { class Program { static IDictionary<string, string> cache = new Dictionary<string, string>() { {"0001","A"}, {"0002","B"}, {"0003","C"}, {"0004","D"}, {"0005","E"}, {"0006","F"}, }; public static void Main() { Task<string> task = GetValueFromCache("0006"); ("The main program continues to execute...."); string result = ; ("result={0}", result); } private static Task<string> GetValueFromCache(string key) { ("GetValueFromCache starts executing...."); string result = ; //(5000); (5000); ("GetValueFromCache continues to execute...."); if ((key, out result)) { return (result); } return (""); } } }
2.6. Process notifications for asynchronous programming using IProgress
IProgress<in T> only provides a method void Report(T value), which reports a T-type value to IProgress through the Report method, and then the constructor of IProgress<in T>'s implementation class Progress<in T> receives formal parameters of type Action<T>, and uses this delegation to display the progress in the UI interface.
using System; using ; using ; namespace ConsoleApp1 { class Program { static void DoProcessing(IProgress<int> progress) { for (int i = 0; i <= 100; ++i) { (100); if (progress != null) { (i); } } } static async Task Display() { //The current thread var progress = new Progress<int>(percent => { (); ("{0}%", percent); }); //Thread pool thread await (() => DoProcessing(progress)); (""); ("Finish"); } public static void Main() { Task task = Display(); (); } } }
2.7. Application (Simple APM mode (delegation) to task) (BeginXXX and EndXXX)
Callback method
using System; using ; using ; namespace ConsoleApp1 { class Program { private delegate string AsynchronousTask(string threadName); private static string Test(string threadName) { ("Starting..."); ("Is thread pool thread: {0}", ); ((2)); = threadName; return ("Thread name: {0}", ); } private static void Callback(IAsyncResult ar) { ("Starting a callback..."); ("State passed to a callbak: {0}", ); ("Is thread pool thread: {0}", ); ("Thread pool worker thread id: {0}", ); } //The execution process is to first execute Test---->Callback---> static void Main(string[] args) { AsynchronousTask d = Test; ("Option 1"); Task<string> task = Task<string>.( ("AsyncTaskThread", Callback, "a delegate asynchronous call"), ); (t => ("Callback is finished, now running a continuation! Result: {0}", )); while (!) { (); ((0.5)); } (); } } }
No callback method
using System; using ; using ; namespace ConsoleApp1 { class Program { private delegate string AsynchronousTask(string threadName); private static string Test(string threadName) { ("Starting..."); ("Is thread pool thread: {0}", ); ((2)); = threadName; return ("Thread name: {0}", ); } //The execution process is to execute Test---> static void Main(string[] args) { AsynchronousTask d = Test; Task<string> task = Task<string>.( , , "AsyncTaskThread", "a delegate asynchronous call"); (t => ("Task is completed, now running a continuation! Result: {0}", )); while (!) { (); ((0.5)); } (); } } }
//Task starts a function task with parameters and return values//The following example test2 is a function with parameters and return values. private int test2(object i) { (new Action(() => { = true; })); (3000); ("hello:" + i); (new Action(() => { = false; })); return 0; } //Test callprivate void call() { //Func<string, string> funcOne = delegate(string s){ return "fff"; }; object i = 55; var t = Task<int>.(new Func<object, int>(test2), i); } //= Download the website source file example == == == == == == == == == == == == == == == == == == == == == ==//HttpClient referenceprivate async Task< int> test2(object i) { (new Action(() => { = true; })); HttpClient client = new HttpClient(); var a = await (""); Task<string> s = (); (); //(3000); //("hello:"+ i); (new Action(() => { = false; })); return 0; } async private void call() { //Func<string, string> funcOne = delegate(string s){ return "fff"; }; object i = 55; var t = Task<Task<int>>.(new Func<object, Task<int>>(test2), i); } //----------or---------- private async void test2() { (new Action(() => { = true; })); HttpClient client = new HttpClient(); var a = await (""); Task<string> s = (); (); (new Action(() => { = false; })); } private void call() { var t = (new Action(test2)); //Equivalent to //Thread th= new Thread(new ThreadStart(test2)); //(); } TaskStart a function task with parameters and return values
The above is the detailed content of the in-depth analysis of C# Task. For more information about C# Task, please follow my other related articles!