Task is a multi-threading technology that builds thread pools, and its emergence makes Thread history. Its usage method is very simple. Let's make a simple example in the top-level statement.
void printN(string name) { for (int i = 0; i < 3; i++) { ($"{name}:{i}"); (1000).Wait(); } } (() => printN("t1")); (() => printN("t2")); (() => printN("t3")).Wait();
After running, the result in the command line is
t3:0
t2:0
t1:0
t2:1
t3:1
t1:1
t1:2
t2:2
t3:2
By entering a delegate, create a task and execute it, and return a Task object.
During execution, the task does not wait for the main thread of the command line, so the last started task is followed by Wait, that is, after the thread is waiting for the end of the thread, the main thread ends, so that the output content of printN can be displayed in the terminal.
Task class
The above case can also be implemented using Task, but after the Task object is created, it will not run immediately, but will run after Start(). The example is as follows
void printN(object name) { for (int i = 0; i < 3; i++) { ($"{name}:{i}"); (1000).Wait(); } } Action<object> act = (object name) => printN(name); Task t1 = new Task(()=>printN("t1")); new Task(act, "t2").Start(); Task t3 = new Task(act, "t3"); (); (); ();
Return value
In addition to Task, C# also provides encapsulation with return values, namely Task<TResult>, which can declare return values through generics.
However, Task is still a class, not a function, and this return value will not be reflected in the constructor, nor will it pass through the Start() function. If you want to use this return value, you need to pass through the ContinueWith function.
The function of ContinueWith is to enable the next thread after a certain thread is executed. If the thread that has been executed has a return value, ContinueWith can also use this return value.
The call method is
Task<int> task = new Task<int>(() => { ("This is a task"); return 100; }); //Execute processing when the task is completed.Task cwt = (t => { ($"here it isContinue,taskThe return value is{}"); }); (); ();
Among them, cwt needs to wait for the task to be executed before executing.
Wait and continue
In the previous case, the basic wait function Wait and the basic continuation function ContinueWith have been explained. More waiting and continuation functions are provided in C# to operate thread lists more flexibly.
Blocking the main thread | Do not block the main thread | |
---|---|---|
Any thread can be executed after it is executed | WaitAny | WhenAny |
All threads can only be executed after they are executed | WaitAll | WhenAll |
Among them, WhenAny and WhenAll need to be eaten in conjunction with ContinueWith. After WhenXX ends, the content in ContinueWith is executed. This process does not block the main thread.
To verify the functionality of these functions, create a list of threads first
Action<string, int> log = (name, time) => { ($"{name} Start..."); (time).Wait(); ($"{name} Stop!"); }; Task[] tasks = new Task[] { (() => log("A",3000)), (() => log("B",1000)), (() => log("C",2000)) };
Then execute these waiting functions in turn to see the results
(tasks); At this time, when B is executed, the blocking ends, and the main thread ends.
B Start...
A Start...
C Start...
B Stop!
(tasks); This time, the program ends after all threads have been executed.
A Start...
B Start...
C Start...
B Stop!
C Stop!
A Stop!
The following two sets of tests have similar phenomena to the first two sets, and the difference is nothing more than adding a string to the back.
(tasks).ContinueWith(x => ($"A certain task has been executed")).Wait(); (()).ContinueWith(x => ("All Tasks are executed")).Wait();
Cancel a task
C# provides CancellationToken as the identifier of Task cancellation. By calling the Cancel() function, its cancel flag can be changed to True, so that it can cancel the thread during thread execution.
First create a thread function that can be cancelled
int TaskMethod(string name, int seconds, CancellationToken token) { ($"{name} Running"); for (int i = 0; i < seconds; i++) { (1000).Wait(); ($"{name}: {i}s"); if () return -1; } return 1; }
The function is very simple, it is to run a loop. During the running loop, if the token indicates cancellation, the thread ends.
Let's test it below
var cts = new CancellationTokenSource(); var task = new Task<int>(() => TaskMethod("Task 1", 5, ), ); ($"Thread status:{}"); (); ($"Thread status:{}"); (3000).Wait(); (); ($"Thread status:{}"); (1000).Wait(); ($"Thread status:{}");
The effect is as follows
Thread status: Created
Thread status: WaitingToRun
Task 1 is running
Task 1: 0s
Task 1: 1s
Thread status: Running
Task 1: 2s
Thread status: RanToCompletion
During the entire thread execution process, four states appear in total
- Created The thread has just been created, but it has not been executed.
- WaitingToRun has executed the Start function at this time, but the thread has not reacted yet, so it is waiting for execution.
- Running has executed Cancel at this time, but the loop in the task is detected every 1 second. After Cancel is executed, the status of the thread is checked before it has time to detect, so the thread is still running.
- RanToCompletion After waiting for 1 second, it finally detected that the token has changed, and the thread ends.
This is the end of this article about the detailed explanation of the Task class of C# concurrent programming. For more related content of the Task class, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!