When a complex asynchronous operation needs to be performed prior to c#4.0, only CLR thread pooling techniques can be used to perform a task. When a thread pool executes an asynchronous task, it does not know when the task is complete, and the task cannot get the return value after the task completes. In c#4.0, however, a task (the type of the System.Threading.Tasks namespace) mechanism is introduced to solve the problem of the completion time of the asynchronous operation and the return value after completion.
1. Create and perform simple tasks using the task class
Create a task by using the task's constructor and call the Start method to start the task and perform an asynchronous operation. When you create a task, you must pass a delegate callback method of the action or action<object> type, and you can select the data object that is required when the delivery task executes, and so on. The constructor for the task class is as follows:
Public Task (Action action);Public Task (action<object> Action, object state); Public Task (Action action, CancellationToken CancellationToken); Public Task (Action action, TaskCreationOptions creationoptions); Public Task (action<object> Action, object state, CancellationToken CancellationToken); Public Task (action<object> Action, object state, TaskCreationOptions creationoptions); Public Task (Action action, CancellationToken CancellationToken, TaskCreationOptions creationoptions); Public Task (action<object> Action, object state, CancellationToken CancellationToken, TaskCreationOptions creationoptions);
Example code:
1: void Main (string[] args)
2: {
3: Console.WriteLine ("Main thread performs business processing.");
4: //Create Task
5: new Task (() = {
6: Console.WriteLine ("Use System.Threading.Tasks.Task to perform asynchronous operations.");
7: For (int i = 0; i < ten; i++)
8: {
9: Console.WriteLine (i);
Ten: }
One: });
: //Start the task and schedule the task to execute on the current task queue thread (System.Threading.Tasks.TaskScheduler)
: task. Start ();
: Console.WriteLine ("Main thread performs other processing");
The main thread hangs for 1000 milliseconds, waiting for the task to complete.
: thread.sleep (1000);
: }
Task Scheduling results:
2. Wait for the task to complete and get the return value
When you use a task to perform an asynchronous operation, the most important is the return value after the task is completed. There is an instance method in the Task class wait (there are many overloaded versions) he can wait for the task to complete, we can also create an asynchronous task from the derived class task<tresult> of the task class, and specify the type of the value to return when the job completes, which can be done by task< The instance object of the tresult> gets the return value after the task completes. Create an asynchronous task and perform a 0 to 100 sum operation to return the final result of the calculation, sample code:
1: void taskwait () {
2: //Create Task
3: task<new task<int> (() =
4: {
5: int sum = 0;
6: Console.WriteLine ("Use task to perform asynchronous operation.");
7: For (int i = 0; i <; i++)
8: {
9: sum+=i;
Ten: }
One: return sum;
: });
: //Start the task and schedule the task to execute on the current task queue thread (System.Threading.Tasks.TaskScheduler)
: task. Start ();
:
: Console.WriteLine ("Main thread performs other processing");
///wait for the task to complete the execution process.
: task. Wait ();
: //Get the execution result of the task
: Console.WriteLine ("Task execution Result: {0}", task.) Result.tostring ());
: }
Execution Result:
The Task class also has some static methods, WaitAll is used to wait for all System.Threading.Tasks.Task objects provided to complete the execution process and wait for any of the System.Threading.Tasks.Task to be provided. object to complete the execution process, both methods have some overloaded versions.
Wait for all tasks to complete void WaitAll (params task[] tasks); Wait for any task to complete int WaitAny (params task[] tasks);
3. Use the ContinueWith method to start a new task when the task is completed
It is possible to block threads when using the wait method for a task class or the result property of a derived class to get the results of a task execution, and in order to solve this problem, the ContinueWith method can be used to automatically start a new task to handle the execution result when a task is completed.
Example code:
1: void Taskcontinuewith ()
2: {
3: //Create a task
4: task<new task<int> (() =
5: {
6: int sum = 0;
7: Console.WriteLine ("Use task to perform asynchronous operation.");
8: For (int i = 0; i <; i++)
9: {
: sum + = i;
One: }
: return sum;
: });
//Start the task and schedule the task to execute on the current task queue thread (System.Threading.Tasks.TaskScheduler)
: task. Start ();
: Console.WriteLine ("Main thread performs other processing");
When the task is completed, the processing is performed.
18:
: Console.WriteLine (
: });
: thread.sleep (1000);
: }
Execution Result:
Instead of waiting for completion to display the result of the execution, the example above uses the ContinueWith method, which knows when the task finishes and starts a new task to perform the task after the completion of the process. The ContinueWith method has some overloaded versions that allow you to specify the data to be used by the continuation task, How the continuation task works (the System.Threading.Tasks.TaskContinuationOptions enumeration value is the result of a bitwise or run), and so on.
4. Creating parent-child tasks and task factory usage
Tasks created through the task class are top-level tasks that can be associated with creating a task by using the Taskcreationoptions.attachedtoparent identity, and all subtasks are completed after the parent task finishes the operation. Examples are as follows:
1: void Parentchildtask () {
2: task<new task<string[]> (state = {
3: Console.WriteLine (state);
4: string[] result=string[2];
5: //Create and start subtasks
6: "I am subtask 1." ";},taskcreationoptions.attachedtoparent). Start ();
7: "I am subtask 2." ";}, Taskcreationoptions.attachedtoparent). Start ();
8: return result;
9: },"I am the parent task and I create multiple subtasks during my processing, and I will not end execution until all subtasks are completed." ");
: //actions performed after task processing is completed
One: parent. ContinueWith (T + = {
: Array.foreach (T.result, R=>console.writeline (R));
: });
: //Start parent Task
: parent. Start ();
: Console.read ();
: }
Execution Result:
If you need to create a set of tasks that have the same state, you can use the TaskFactory class or the Taskfactory<tresult> class. These two classes create a set of tasks that can specify the CancellationToken, TaskCreationOptions, taskcontinuationoptions, and TaskScheduler default values for a task. Example code:
1: void taskfactoryapply ()
2: {
3: new Task (() =
4: {
5: new CancellationTokenSource (the);
6: //Create a task factory
7: new TaskFactory (CTS. Token, Taskcreationoptions.attachedtoparent, taskcontinuationoptions.executesynchronously, TaskScheduler.Default) ;
8: //Add a group of subtasks with the same status
9: new task[]{
Ten: TF. StartNew (() + = {Console.WriteLine ("I am the first task in the Mission Factory.") "); }),
One: TF. StartNew (() + = {Console.WriteLine ("I am the second task in the Mission Factory.") "); }),
: TF. StartNew (() = {Console.WriteLine ("I am the third task in the Mission factory. "); })
: };
: });
: parent. Start ();
: Console.read ();
: }
Execution Result:
5. Task internal implementation and task scheduling
Within a task, there is a set of properties that make up the status of the task, the unique ID of the task, the execution state (TaskStatus) that represents the task, the reference to the callback function that was provided when the task was created, and the data object passed to the callback function asyncstate, A reference to the task dispatch object (TaskScheduler) when the task was created, a reference to the parent task, and a reference to the execution context and the ManualResetEventSlim object. Both the task class and the Task<tresult> class implement the standard interface for freeing resources, allowing the Dispose method to release resources when the task finishes processing (Close the ManualResetEventSlim object instance). You can use the CurrentID property of the task class to get the ID of the task being executed, and if no task is executed CurrentID the return value is null,currentid an int? An attribute of the nullable type. The life cycle of a task execution is represented by a value of type TaskStatus, the value that TaskStatus contains:
Enum TaskStatus { Created = 0, waitingforactivation = 1, Waitingtorun = 2, Running = 3, Waitingforchildrentocomplete = 4, rantocompletion = 5, Canceled = 6, Faulted = 7, }
We can get all the exceptions during the execution of the task through the exception property of the Tasks class
, exception is a property of type AggregateException. The task class provides iscanceled, IsCompleted, and isfaulted properties to get the completion status of a task. Subsequent tasks created through ContinueWith, Continuewhenall, Continuewhenany, and FromAsync are in the waitingforactivation state, and the tasks of this state are automatically executed when the parent task completes.
The execution of the task is dispatched internally by the TaskScheduler class, which is an abstract class, The FCL derives two derived classes from him: The Threadpooltaskscheduler thread Pool Task Scheduler and the Synchronizationcontexttaskscheduler Synchronization context Task Scheduler. All tasks default to the Threadpooltaskscheduler dispatch task, which uses a thread pool to perform tasks, and can obtain a reference to the default task scheduler through the static property default of the TaskScheduler class. Synchronizationcontexttaskscheduler Task Scheduler can be used in Windows Form, WPF and other applications, his Task Scheduler is the use of the GUI thread, so he can synchronize updates UI components, A reference to a synchronization context task schedule can be obtained by fromcurrentsynchronizationcontext the static method of the TaskScheduler class.
Task Scheduling Example:
1: void button1_click (object sender, EventArgs e)
2: {
3: //Get Synchronization Context Task Scheduler
4: TaskScheduler M_synccontexttaskscheduler = Taskscheduler.fromcurrentsynchronizationcontext ();
5:
6: //Create tasks and perform tasks with the default task Scheduler (thread Pool Task Scheduler)
7: task<new task<int> (() =
8: {
9: //perform complex computational tasks.
Ten: Thread.Sleep (2000);
One: int sum = 0;
: For (int i = 0; i <; i++)
: {
Sum: + + i;
: }
: return sum;
: });
: var cts=new CancellationTokenSource ();
: //When the task completes, a successor task is initiated and the UI component is updated with the synchronization Context Task Scheduler Schedule task.
: task. ContinueWith (t + = {this.label1.text=)updates the UI with the Synchronizationcontexttaskscheduler Task Scheduler. \ r \ n The calculated result is: "+task. Result.tostring (); },
: CTS. Token, Taskcontinuationoptions.attachedtoparent,m_synccontexttaskscheduler);
: task. Start ();
: }
Execution Result:
This article simply describes the use of the task class to perform asynchronous operations and the internal implementation of tasks and task scheduling. When performing complex asynchronous operations, tasks can be performed, and he is better able to know when an asynchronous operation completes and returns the execution result of an asynchronous operation.
Go to C # Threading Knowledge-using task to perform asynchronous operations