Task对象内部是否包含ContinueWith任务的集合



我正在读一本书,上面写着:

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只是将一个项添加到集合中,那么ab应该指向同一个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类并对其进行检查,您可以看到,虽然它本身不一定是一个集合,但它以线程安全的方式保持并维护延续。

最新更新