C# Task 源代码(2)

时间:2022-06-24 08:54:36

上篇已经讲到Task 的默认的TaskScheduler 为ThreadPoolTaskScheduler.

这时我们回到原来的task 的start方法,在代码最后,调用了 ScheduleAndStart(true) 这个方法。接着看这个方

[SecuritySafeCritical] // Needed for QueueTask internal void ScheduleAndStart(bool needsProtection) { Contract.Assert(m_taskScheduler != null, "expected a task scheduler to have 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 other task than TaskContinuations we want to log. TaskContinuations log in their constructor AsyncCausalityTracer.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 = new TaskSchedulerException(e); AddException(tse); Finish(false); // Now we need to mark ourselves as "handled" to avoid crashing the finalizer thread if we are called from StartNew() // or from the self replicating logic, because in both cases the exception is either propagated outside directly, or added // to an enclosing parent. However we won‘t do this for 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 have faults recorded."); m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false); } // re-throw the exception wrapped as a TaskSchedulerException. throw tse; } }

开始先做契约参数认证,接着保护数值判断。我们要看的是AddToActiveTasks(this)这个方法,注意在他之前有个判断,在s_asyncDebuggingEnabled 为true 的情况才会执行,当然默认的是false。

// This dictonary relates the task id, from an operation id located in the Async Causality log to the actual // task. This is to be used by the debugger ONLY. Task in this dictionary represent current active tasks. private static readonly Dictionary<int, Task> s_currentActiveTasks = new Dictionary<int, Task>(); [FriendAccessAllowed] internal static bool AddToActiveTasks(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; }