任务延续中的副作用是否总是可见的?
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
- 即它支持没有直接从任务交付任何内容的场景继续。
副作用是否保证在任务延续中可见?
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
- 即它支持没有直接从任务交付任何内容的场景继续。