在任何情况下,异步等待方法中的对象更改在完成后是否可见?

Are object changes inside async await methods visible after completion in any case?

async/await 方法内的对象更改在任何情况下都可见吗?

经过大量调查,我仍然找不到明确的声明,如果在完成等待 in 之后,从异步等待方法内部对外部对象进行的更新对后续代码可见案例.

代码示例是某种过滤器链,其中每个过滤器都应该看到之前过滤器所做的任何更改。之后,将使用相同的对象进行进一步处理。

没有并行执行过滤器。除此之外,由于性能原因,我不想克隆对象。

请看下面的代码示例:

class Program
{
    private List<ICallback> _allCallbacks = new List<ICallback>();

    public Program()
    {
        // Setup callbacks, perhaps by dependency injection
        _allCallbacks.Add(new MyCallback1());
        _allCallbacks.Add(new MyCallback2());
    }

    static async Task Main()
    {
        Program p = new Program();
        await p.RunBusinessLogic();
        Console.ReadLine();
    }

    private async Task RunBusinessLogic()
    {
        MyDto dto = new MyDto();

        // Setting initial value
        dto.TestProperty = "start";

        // Execute all callbacks and await completion
        await ExecuteCallbacks(dto).ConfigureAwait(false);

        // *** Is dto.TestProperty always guaranteed to be most current value ***?
        Console.WriteLine(dto.TestProperty); // start-1-2?
    }

    public async Task ExecuteCallbacks(MyDto source)
    {
        foreach (ICallback callback in _allCallbacks)
        {
            // Execute Callbacks one after the other, no parallel execution here
            await callback.OnCallback(source).ConfigureAwait(false);
        }
    }

    public class MyDto
    {
        public string TestProperty { get; set; }
    }

    public interface ICallback
    {
        public Task OnCallback(MyDto dto);
    }

    public class MyCallback1 : ICallback
    {
        public async Task OnCallback(MyDto x)
        {
            x.TestProperty += "-1";
            await Task.CompletedTask.ConfigureAwait(false);
        }
    }

    public class MyCallback2 : ICallback
    {
        public async Task OnCallback(MyDto x)
        {
            x.TestProperty += "-2";
            await Task.CompletedTask.ConfigureAwait(false);
        }
    }
}

可能相关:

这是一个非常合理的担忧,如果 C# 规范和 CLI 规范都有更清晰的内存模型来保证这一点,那就太好了。

不,我不相信有任何 Microsoft 记录 保证当任务完成(无论是成功还是失败)并且继续执行时,所有内存都会改变在任务中执行对后续代码可见。

但是,我相信 务实的现实 是的,所有更改都将是可见的,就好像在任务完成时存在完整的内存障碍一样。看起来像 Joe Albahari asserts that this is the case,但我希望看到更多“出自马口”的保证。

JIT 编译器在理论上 允许做的事情还有其他一些类似的方面 - 这比 JIT 编译器作者认为合理的要多得多做。随着时间的推移,我希望看到关于此的更详细的保证,但我对这种情况的发生并没有太大的信心。