我正在读一本书,上面写着:
Task对象内部包含ContinueWith任务的集合。因此,您实际上可以使用单个Task对象多次调用ContinueWith。当任务完成后,所有ContinueWith任务都将排队到线程池中。
所以我尝试检查Task的源代码https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,146
我没有找到任何看起来像ContinueWith任务集合的私有字段。
所以我的问题是,Task对象内部是否包含ContinueWith任务的集合?
如果是这样,假设我们有以下代码:
Task<Int32> t = Task.Run(() => Sum(10000));
Task a = t.ContinueWith(task => Console.WriteLine("The sum is: " + task.Result),
TaskContinuationOptions.OnlyOnRanToCompletion);
Task b = t.ContinueWith(task => Console.WriteLine("Sum threw: " + task.Exception.InnerException),
TaskContinuationOptions.OnlyOnFaulted);
if (a == b) {
... // false
{
由于调用ContinueWith
只是将一个项添加到集合中,那么a
和b
应该指向同一个Task对象,但a == b
返回false?
我想你可以说答案是肯定的和否定的。Task类使用Interlocked来跟上继续。
您可以在第4727行看到添加名为AddTaskContinuationComplex(对象tc,bool-addBeforeOthers(的延续的方法。在这个方法中,continuation被添加到一个列表中,然后被传递到Interlocked。
// Construct a new TaskContinuation list
List<object> newList = new List<object>();
// Add in the old single value
newList.Add(oldValue);
// Now CAS in the new list
Interlocked.CompareExchange(ref m_continuationObject, newList, oldValue);
现在,如果您查看FinishContinuations(第3595行(方法,您可以看到
// Atomically store the fact that this task is completing. From this point on, the adding of continuations will
// result in the continuations being run/launched directly rather than being added to the continuation list.
object continuationObject = Interlocked.Exchange(ref m_continuationObject, s_taskCompletionSentinel);
TplEtwProvider.Log.RunningContinuation(Id, continuationObject);
在这里,当前任务被标记为已完成,下一个任务从Interlocked获得。
现在,如果您转到Interlocked类并对其进行检查,您可以看到,虽然它本身不一定是一个集合,但它以线程安全的方式保持并维护延续。