C # Reading Task source code (1 ),

Source: Internet
Author: User

C # Reading Task source code (1 ),

We usually use tasks during development. Many of the later. net versions are related to tasks, such as asyn and await. We seldom pay attention to threads when we have tasks. Task brings us a lot of convenience. We focus less on the execution process and more on logic. But sometimes there are some applications. You have to consider the running status of the task, such as whether the task is successful or not and whether an exception has occurred. It is often said that tasks are executed in the thread pool. Today, let's take a look at what the task is doing and what it does when it is executed.

You can see the source code of the Task from here, or download it directly from the reference code.

Let's take a look at this code.

public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable    {        [ThreadStatic]        internal static Task t_currentTask;  // The currently executing task.        [ThreadStatic]        private static StackGuard t_stackGuard;  // The stack guard object for this thread        internal static int s_taskIdCounter; //static counter used to generate unique task IDs        private readonly static TaskFactory s_factory = new TaskFactory();        private volatile int m_taskId; // this task's unique ID. initialized only if it is ever requested        internal object m_action;    // The body of the task.  Might be Action<object>, Action<TState> or Action.  Or possibly a Func.        // If m_action is set to null it will indicate that we operate in the        // "externally triggered completion" mode, which is exclusively meant         // for the signalling Task<TResult> (aka. promise). In this mode,        // we don't call InnerInvoke() in response to a Wait(), but simply wait on        // the completion event which will be set when the Future class calls Finish().        // But the event would now be signalled if Cancel() is called}

First, let's look at the interface inherited by the Task class. The IThreadPoolItem is related to the thread pool. The IAsyncResult is related to the callback of asynchronous execution. I will not talk about it too much here,

Then we can see that there is a field t_currentTask, Which is static and points to its own task. I don't know if there will be any doubt. Why is this design? In fact, this design is available in. net in many places, such as HttpContext. Basically, there will be a Current feature. This is a bit similar to the singleton mode, but it has been initialized. you can replace it at any time to inject your own defined items. It is completely OK to use it as a singleton. Note that the access modifier here is internal static.

Then t_stackGuard and s_taskIdCounter are not described too much.

Below is s_factory. Note that it is static and access modifier. Of course, if I use the factory mode, the current factory is rarely used inside the class. Of course I have to do this for the finished products I want to produce.

Next, an important field m_action is executed. Do you remember how to execute the so-called function in the Assembly, push a push B call xxxx. A and B are parameters respectively, and xxxx is the jump address for code execution. parameter transmission is generally carried through stack. Put the object directly in. net, and the annotation is clearly nothing more than the delegate. But for a function, its execution body is the call address.

Next, let's look at the following fields.

        internal object m_stateObject; // A state object that can be optionally supplied, passed to action.        internal TaskScheduler m_taskScheduler; // The task scheduler this task runs under.         internal readonly Task m_parent; // A task's parent, or null if parent-less.        internal volatile int m_stateFlags;

M_stateObject can be guessed until it works.

The following is an extremely important field m_taskScheduler in the execution process. Generally, taskScheduler on windows platforms may be used in many ways. When it comes to taskScheduler, the function is to schedule tasks reasonably and is actually an execution manager. Of course, we have similar jobs in SQL server development tools. For job execution, we also need to select the execution plan. Of course, m_taskScheduler here may be a task scheduler. Of course, the default taskScheduler of tasks is a little different from the functions of the tool we just mentioned. Of course, you have an impression that it is used to schedule tasks. There are different solutions for scheduling.

M_stateFlags status flag field. Of course, I would like to understand the execution of a Task until it is in the current state, starting and ending. There are many statuses in Thread mode.

Continue viewing code

   public void Start()        {            Start(TaskScheduler.Current);        }public void Start(TaskScheduler scheduler)        {            // Read the volatile m_stateFlags field once and cache it for subsequent operations            int flags = m_stateFlags;            // Need to check this before (m_action == null) because completed tasks will            // set m_action to null.  We would want to know if this is the reason that m_action == null.            if (IsCompletedMethod(flags))            {                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_TaskCompleted"));            }            if (scheduler == null)            {                throw new ArgumentNullException("scheduler");            }            var options = OptionsMethod(flags);            if ((options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0)            {                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_Promise"));            }            if ((options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) != 0)            {                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_ContinuationTask"));            }            // Make sure that Task only gets started once.  Or else throw an exception.            if (Interlocked.CompareExchange(ref m_taskScheduler, scheduler, null) != null)            {                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_AlreadyStarted"));            }            ScheduleAndStart(true);        }

 

We usually use the start method, which will pass in a taskschedstart by default. Let's take a look at the following method, and finally call the ScheduleAndStart method. Regardless of the previous verification, we focus on the execution process, to understand this, we must understand TaskScheduler. current

What is the class, what is its function? If we write TaskScheduler ourselves, what should we write and what functions should we complete.

We continue to find the TaskScheduler class from the reference code. We should first focus on tracking Current, regardless of the method.

 public static TaskScheduler Current         {            get            {                TaskScheduler current = InternalCurrent;                return current ?? TaskScheduler.Default;            }        } internal static TaskScheduler InternalCurrent        {            get            {                Task currentTask = Task.InternalCurrent;                return ( (currentTask != null)                     && ((currentTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)                    ) ? currentTask.ExecutingTaskScheduler : null;            }        }

 

By default, I continue to find the default Property
public static TaskScheduler Default         {            get            {                return s_defaultTaskScheduler;            }        }   private static readonly TaskScheduler s_defaultTaskScheduler = new ThreadPoolTaskScheduler();

 

We tracked it step by step and finally found ThreadPoolTaskScheduler. At this moment, we can finally connect the task to threadpool.

Before executing ScheduleAndStart, let's take a look.
If (Interlocked. CompareExchange (ref m_taskScheduler, scheduler, null )! = Null) The expression of this sentence, null judgment plus the value assignment of the object. This can be borrowed from the usual code.



 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.