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

标签 c# .net .net-core async-await memory-model

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

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

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

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

请参阅以下代码示例:

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);
        }
    }
}

可能相关:Do async and await produce acquire and release semantics?

最佳答案

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

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

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

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

关于c# - 在任何情况下,异步等待方法内的对象更改在完成后是否可见?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63195626/

相关文章:

c# - 字符串如何在 C# 中终止?

.net - 如何指定MessageBodyMember是必需的?

c# - 如何配置套接字连接超时

c# - 存储表格数据结构的最佳类型是什么?

c# - 带有 Html 内容占位符的 ASP.NET 通用用户控件

c# - 如何在 WPF 的一个 XAML 文件中添加多个类文件

c# - 使用 HttpClient 发送大量请求的最快和最安全的方法是什么?

c# - 英孚核心 2.1。将自定义列添加到 MigrationHistory 表

c# - 如何在 Razor Page OnInitialized 事件中使用 404 路由

c# - ASP.NET MVC 返回超过预期