我们今天要试着解决昨天阅读 WhenAll 留下来的两个问题
当 WhenAll 检测到尚未完成的任务时会进入 task.AddCompletionAction(this);
这里的 task 是待完成列表的其中一个任务, this 是运行 WhenAll 的本人。
跳过层层包装我们会看到
private void AddCompletionAction(ITaskCompletionAction action, bool addBeforeOthers)
{
if (!AddTaskContinuation(action, addBeforeOthers))
action.Invoke(this);
}
当 AddTaskContinuation(action, addBeforeOthers)
为 false 表示任务已经完成, 在这里调用 WhenAll 中的 Invoke 把待完成任务总数减1。
接着我们了解一下 AddCompletionAction
里面发生甚麽事
private bool AddTaskContinuation(object tc, bool addBeforeOthers)
{
Contract.Requires(tc != null);
// 检测目前所在执行列表里的任务, 是否完成
if (IsCompleted) return false;
// 利用 CAS 把 tc ( WhenAllPromis 这个物件 ) 送入连续任务
if ((m_continuationObject != null) || (Interlocked.CompareExchange(ref m_continuationObject, tc, null) != null))
{
// 当一般 CAS 方法失败後用这个一定成功的 CAS 方法。 不细讲
return AddTaskContinuationComplex(tc, addBeforeOthers);
}
else return true; // 回传 true, 成功把 WhenAllPromise 加入到这个执行列表里的任务的连续任务区。
}
注 : WhenAllPromise 事当我们调用 WhenAll 所生成的物件, 上一篇文提到的事情都是在, WhenAllPromise 发生的
当 WhenAllPromise 这个物件被送入连续任务後发生了什麽呢 ?
这个疑问会在之後解答, 因为这个 method 就写到这里了。
当 Task.WhenAll( taskList )
调用後执行动作
taskList = 待完成任务列表, 我自己命名的变数
WhenAllPromise
物件, 且传入 taskListWhenAllPromise
物件中WhenAllPromise
内部执行依序扫描 taskList 内的 taskWhenAllPromise
有可能被挂载到别的 task 执行, 就会被视为 multi-thread )WhenAllPromise
的 reference 挂载到 未完成的 task 的连续任务区(这个名词是我自己取的 XD )WhenAllPromise
内的未完成任务数量为0, 表示任务全部完成, 当即设置回传变数, 与进行回传。WhenAllPromise
有在上面的第 5 步挂载到别的 task。WhenAllPromise
不会结束。至於被挂载进连续任务区的任务会被如何处理, 会在 Day 10 跟大家解释清楚。值得注意的是因为每个 task 的连续任务区都有可能在任何时刻, 被别的 thread 添加, 因此也被设计成一个 lock-free data structure.
另外, 未完成任务数量因为WhenAllPromise
被挂载到别条 thread , 为了避免 race condition 也用了 atomic 变数。
开始看看 task 的创建, 试着了解 task 的生命历程吧。
明天见!
使用 React useState Hook 创建数字时钟 import React, {useSt...
首先从生成模式开始,第一种生成模式是 abstract factory (抽象工厂) 抽象工厂的目的...
上一篇先介绍运用的知识点,这篇会着重在实作时的心路历程...不是啦,是怎麽把这个网页写出来的。先上成...
在我开始介绍Google Cloud Platform的Google app engine之前,我想...
经过了昨天的介绍,今天就来看看使用登入范例罗 今天的登入资料依然是使用 FakeStoreAPI 登...