【问题标题】:Are side effects always visible in task continuations?在任务延续中是否总是可见副作用?
【发布时间】:2020-04-02 07:02:25
【问题描述】:

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

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

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

【问题讨论】:

  • 我不认为有任何正式记录,但如果不能保证您看到任务的效果,那么继续将毫无用处。
  • @Damien_The_Unbeliever 我猜延续通常会直接使用任务结果,所以他们不会受到这个问题的困扰。

标签: .net task side-effects


【解决方案1】:

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

如果那是“某处是否有一些来自 MS 的官方文档是这样说的”,那么恐怕答案是否定的。

实际上,如果他们不能依赖能够观察到他们从1 继续的任务所产生的所有效果,那么延续将毫无用处。

.NET Framework 4.8 sourcecore clr 都有一个名为FinishContinuations 的内部方法,用于查找Task 对象具有的延续并导致它们被调度/执行。在这两种实现中,Interlocked.Exchange 用于获取延续对象,希望您已经意识到这会带来完整的内存屏障。


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

我还检查了BotR,但找不到任何关于此的具体声明。


1请记住,我们可以有Task.ContinueWith,而不仅仅是Task<T>.ContinueWith - 即它支持没有任何东西直接从任务传递到延续的场景。

【讨论】:

    猜你喜欢
    • 2014-05-23
    • 2023-03-16
    • 2020-06-20
    • 2023-03-29
    • 2017-04-26
    • 2019-04-26
    • 2013-11-18
    • 1970-01-01
    • 2019-03-15
    相关资源
    最近更新 更多