Task and task
A task indicates the work of a unit that should be completed. The work of this unit can be run in a separate thread, or a task can be started in synchronous mode, which requires waiting for the main call thread. By using tasks, you can not only obtain an abstraction layer, but also control the underlying threads.
1. Start the task
To Start a Task, you can use the TaskFactory class or the constructor of the Task class and the Start () method. The constructor of the Task class provides greater flexibility in Task creation.
1). Task Method
Static object taskMethodLock = new object (); static void TaskMethod (object title) {lock (taskMethodLock) {Console. writeLine (title); Console. writeLine ("Task id: {0}, thread: {1}", Task. currentId = null? "No task": Task. currentId. toString (), Thread. currentThread. managedThreadId); Console. writeLine ("is pooled thread: {0}", Thread. currentThread. isThreadPoolThread); Console. writeLine ("is background thread: {0}", Thread. currentThread. isBackground); Console. writeLine ();}}View Code
2). tasks using the thread pool
Static void TasksUsingThreadPool () {var tf = new TaskFactory (); Task t1 = tf. startNew (TaskMethod, "using a task factory"); Task t2 = Task. factory. startNew (TaskMethod, "factory via a task"); var t3 = new Task (TaskMethod, "using a task constructor and Start"); t3.Start (); Task t4 = Task. run () => TaskMethod ("using the Run method "));}View Code
Execution result:
3). Synchronization task
The task can also run synchronously. The same thread has been used as the main call thread.
Note: The main thread is a front-end call thread without a task ID or a thread in the thread pool.
Private static void RunSynchronousTask () {TaskMethod ("just the main thread"); var t1 = new Task (TaskMethod, "run sync"); t1.RunSynchronously ();}View Code
Execution result:
4). Use a single-threaded task
If the task code should run for a long time, use TaskCreationOptions. LogRunning to tell the task scheduler to create a new thread instead of using the thread in the thread pool.
Private static void LongRunningTask () {var t1 = new Task (TaskMethod, "long running", TaskCreationOptions. LongRunning); t1.Start ();}View Code
Execution result:
2. Future -- Task result
When the task ends, it can write some useful status information to the shared object. This object must be thread-safe. Another option is to use a task that returns a result. This type of task is also called Future because it returns a result.
Static Tuple <int, int> TaskWithResult (object division) {Tuple <int, int> div = (Tuple <int, int>) division; int result = div. item1/div. item2; int reminder = div. item1 % div. item2; Console. writeLine ("task creates a result... "); return Tuple. create <int, int> (result, reminder );}View Code static void ResultsFromTasks () {var t1 = new Task <Tuple <int, int> (TaskWithResult, Tuple. create <int, int> (8, 3); t1.Start (); Console. writeLine (t1.Result); t1.Wait (); Console. writeLine ("result from task: {0} {1}", t1.Result. item1, t1.Result. item2 );}View Code
Execution result:
3. Continuous tasks
You can specify that another task should start after the task is completed.
Note: No matter how the previous task ends, the previous continuous task is always started at the end of the previous task. You can specify the value in TaskContinuationOptions to enable a continuous task only when the start task ends successfully (or fails. Possible values are OnlyOnFaulted, NotOnFaulted, OnlyOnCanceled, and OnlyOnRanToCompletion.
Static void DoOnFirst () {Console. writeLine ("doing some task {0}", Task. currentId); Thread. sleep (3000);} static void DoOnSecond (Task t) {Console. writeLine ("task {0} finished", t. id); Console. writeLine ("this task id {0}", Task. currentId); Console. writeLine ("do some cleanup"); Thread. sleep (3000);} static void DoOnError (Task t) {Console. writeLine ("task {0} had an error! ", T. Id); Console. WriteLine (" my id {0} ", Task. CurrentId); Console. WriteLine (" do some cleanup ");}View Code static void ContinuationTask () {Task t1 = new Task (DoOnFirst); Task t2 = t1.ContinueWith (DoOnSecond); Task t3 = t1.ContinueWith (DoOnSecond ); task t4 = t2.ContinueWith (DoOnSecond); Task t5 = t1.ContinueWith (DoOnError, TaskContinuationOptions. onlyOnFaulted); t1.Start (); Thread. sleep (5000 );}View Code
Execution result:
4. Task hierarchy
With Task continuity, you can start another task after a task is completed. A task can also constitute a hierarchy. When a task starts a new task, a parent/child hierarchy is started.
If the parent task ends before the child task, the status of the parent task is WaitingForChildrenToComplete. When all sub-tasks are completed, the parent task status changes to RanToCompletion.
Static void ParentAndChild () {var parent = new Task (ParentTask); parent. start (); Thread. sleep (1, 2000); Console. writeLine (parent. status); Thread. sleep (1, 4000); Console. writeLine (parent. status);} static void ParentTask () {Console. writeLine ("task id {0}", Task. currentId); var child = new Task (ChildTask); //, TaskCreationOptions. detachedFromParent); child. start (); Thread. sleep (1, 1000); Console. writeLine ("parent started child"); // Thread. sleep (3000);} static void ChildTask () {// Console. writeLine ("task id {0}, parent: {1}", Task. current. id, Task. current. parent. id); Console. writeLine ("child"); Thread. sleep (1, 5000); Console. writeLine ("child finished ");}View Code
Execution result: