任务延续中的副作用是否总是可见的?

Are side effects always visible in task continuations?

副作用是否保证在任务延续中可见?

object o = null;
Task.Run (() => o = new object ())
    .ContinueWith (t => o.ToString ());

延续可能 运行 在与第一个任务不同的线程上。如果没有内存栅栏,对 o 的分配可能对延续不可见。在这种情况下,将抛出 NullReferenceException。在上面的例子中有什么已经阻止了这个吗?

Are side effects guaranteed to be visible in task continuations?

如果那是 "is there some official documentation from MS somewhere that says so" 那么恐怕答案是否定的。

作为一个实际问题,如果他们不能依赖于能够观察他们从1继续的任务所产生的所有影响,那么延续就没有用了。 =19=]

.NET Framework 4.8 source and the core clr 都有一个名为 FinishContinuations 的内部方法,用于查找 Task 对象具有的延续,并使它们成为 scheduled/executed。在这两种实现中,Interlocked.Exchange 用于获取延续对象,希望您已经意识到这会造成完整的内存障碍。


我还发现了这个 Blog Post(不是来自 MS),其中包含强制记忆障碍的项目列表。任务完成情况在列表中,但没有任何对更权威来源的引用。

我也检查了 BotR 但找不到任何关于此的具体说明。


1请记住,我们可以 Task.ContinueWith,而不仅仅是 Task<T>.ContinueWith - 即它支持没有直接从任务交付任何内容的场景继续。