C # Task source code (2)

Source: Internet
Author: User

The default taskscheduler for a task that has been mentioned in the previous article is Threadpooltaskscheduler.

At this point we return to the original task's Start method, and at the end of the code, call the Scheduleandstart (True) method. Then look at this square method.

[SecuritySafeCritical]//Needed for QueueTask        Internal voidScheduleandstart (BOOLneedsprotection) {Contract.assert (M_taskscheduler!=NULL,"expected a task scheduler to the been selected"); Contract.assert ((m_StateFlags& task_state_started) = =0,"task has already started"); //Set the task_state_started bit            if(needsprotection) {if(!markstarted ()) {                    //A Cancel has snuck in before we could get started. Quietly exit.                    return; }            }            Else{m_stateflags|=task_state_started; }            if(s_asyncdebuggingenabled) {addtoactivetasks ( This); }            if(Asynccausalitytracer.loggingon && (Options & (TaskCreationOptions) Internaltaskoptions.continuationtask) = =0)            {                //For all of the other tasks than taskcontinuations we want to log. Taskcontinuations Log in their constructorAsynccausalitytracer.traceoperationcreation (causalitytracelevel.required, This. Id"Task:"+ ((Delegate) m_action). Method.name,0); }            Try            {                //Queue to the indicated scheduler.M_taskscheduler.internalqueuetask ( This); }            Catch(ThreadAbortException tae) {addexception (tae); Finishthreadabortedtask (true,false); }            Catch(Exception e) {//The Scheduler had a problem queueing this task. Record the exception, leaving this task in//a Faulted state.Taskschedulerexception TSE =Newtaskschedulerexception (e);                Addexception (TSE); Finish (false); //Now we need to mark ourselves as "handled" to avoid crashing the finalizer thread if we is called from StartNew () //or from the self replicating logic, because in both cases the exception is either propagated outside directly, or add Ed//To an enclosing parent. However we won ' t do the-continuation tasks, because in that case we internally eat the exception//and therefore we need to make sure the user does later observe it explicitly or see it on the finalizer.                if(Options & (taskcreationoptions) internaltaskoptions.continuationtask) = =0)                {                    //M_contingentproperties.m_exceptionsholder *should* already exist after addexception ()Contract.assert ((m_contingentproperties!=NULL) &&(M_contingentproperties.m_exceptionsholder!=NULL) &&(m_contingentProperties.m_exceptionsHolder.ContainsFaultList), "Task.scheduleandstart (): expected M_contingentproperties.m_exceptionsholder to exist"+"And to has faults recorded."); M_contingentProperties.m_exceptionsHolder.MarkAsHandled (false); }                //Re-throw The exception wrapped as a taskschedulerexception.                ThrowTSE; }        }

Start with the contract parameter certification, and then protect the numerical judgment. What we want to see is addtoactivetasks (this) method, note that before he has a judgement, in the case of s_asyncdebuggingenabled is true will be executed, of course, the default is False.

  //This dictonary relates the task ID, from a operation ID located in the Async causality log to the actual //task. Used by the debugger only. Task in the dictionary represent current active tasks.        Private Static ReadOnlydictionary<int, task> s_currentactivetasks =Newdictionary<int, task>(); [Friendaccessallowed]Internal Static BOOLaddtoactivetasks (Task Task) {Contract.Requires (Task!=NULL,"Null Task objects can ' t be added to the Activetasks collection"); Lock(s_activetaskslock) {s_currentactivetasks[task. ID]=task; }            //Always return true to keep signature as bool for backwards compatibility            return true; }

This is stiff. What is the purpose of putting the task object into a dictionary? It is of course why it is convenient to inquire and manage. This method is not executed in the normal process. There is a strange notation here, where the Task class has a static static dictionary that holds the collection of classes that it executes. Of course, when it comes to management and inquiry, I am not going to put this class in order to make a new class.

Here the code method parameter validation is the use of contract verification, in fact, I personally do not quite agree with this thing, although C + + has this. I would prefer the original exception to be thrown, or logging, or any other custom way.

Then look at the core method M_taskscheduler.internalqueuetask (this); We have seen the default M_taskscheduler as Threadpooltaskscheduler. Then look at the code

[SecurityCritical]Internal voidInternalqueuetask (Task Task) {Contract.Requires (Task!=NULL); Task. Firetaskscheduledifneeded ( This);  This.        QueueTask (Task); } [SecurityCritical]protected Internal Override voidQueueTask (Task Task) {if(Task. Options & taskcreationoptions.longrunning)! =0)            {                //Run longrunning tasks on their own dedicated thread.Thread thread =NewThread (s_longrunningthreadwork); Thread. IsBackground=true;//Keep This thread from blocking process shutdownthread.            Start (Task); }            Else            {                //Normal handling for non-longrunning tasks.                BOOLForcetoglobalqueue = (Task. Options & taskcreationoptions.preferfairness)! =0);            Threadpool.unsafequeuecustomworkitem (task, forcetoglobalqueue); }        }

So far it has become clear that, seeing the Queuetask method, I can already see that the Task object has been uploaded to ThreadPool. At this point, it can be said that tasks are generally run in ThreadPool. Then we look at Threadpooltaskscheduler and let's take a few important steps.

[SecurityCritical]protected Internal Override BOOLTrydequeue (Task Task) {//just delegate to TP            returnThreadpool.trypopcustomworkitem (Task); } [SecurityCritical]protected OverrideIenumerable<task>getscheduledtasks () {returnFiltertasksfromworkitems (Threadpool.getqueuedworkitems ()); }        /// <summary>        ///This internal function would do this:///(1) If the task had previously been queued, attempt to pops it and return false If that fails. ///(2) Propagate the return value from Task.executeentry () to the caller. ///         ///IMPORTANT Note:tryexecutetaskinline would not throw a task exceptions itself. Any wait code path using the This function needs///to account for exceptions this need to be propagated, and throw themselves accordingly. /// </summary>[SecurityCritical]protected Override BOOLTryexecutetaskinline (Task task,BOOLtaskwaspreviouslyqueued) {-----------------------  
   
1. General practice, since many people like the taskfactory.startnew (), so it is troublesome to add all the tasks to a queue, Because the start task is written a lot. Therefore the inside of the individual task handles the exception itself, which writes a good log.
2. Use TaskScheduler, see the purpose of the code in addition to understanding the operation process, and more understanding of such as and use of this class, we only need to write their own taskscheduler , of course, inheriting this class, is the need to implement certain necessary methods, whether it is a task start or TaskFactory StartNew method, we can inject their own taskscheduler, so as TaskScheduler design originally, All task runs will be administered to him, and the default Threadpooltaskscheduler is not available (access modifiers), unless some other means are introduced here. So you can only re-implement the relevant details of this class.

C # Task source code (2)

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.