在Interlocked.Exchange中使用await会使C#编译器崩溃

ria*_*njs 20 c# interlocked compiler-bug async-await

忽略了片刻的荒谬await荷兰国际集团的Enumerable.Range电话.只是在那里引发崩溃行为.它就像一个方法,可以做一些网络IO来构建一个值对象的集合.(的确,这是我看到崩溃发生的地方.)

如果我注释掉该Interlocked.Exchange行,编译器不会崩溃.

public class Launcher
{
    private static IEnumerable<int> _foo;
    static void Main(string[] args)
    {
        DoWorkAsync().Wait();
    }

    private static async Task DoWorkAsync()
    {
        RefreshCache();
        foreach (var element in _foo)
        {
            Console.WriteLine(element);
        }

        Console.ReadLine();
    }

    private static async void RefreshCache()
    {
        Interlocked.Exchange(ref _foo, await Cache());
    }

    private static async Task<IEnumerable<int>> Cache()
    {
        return Enumerable.Range(0, 10);
    }
}
Run Code Online (Sandbox Code Playgroud)

更改RefreshCache()为此可防止编译器崩溃:

private static async void RefreshCache()
{
    var foo = await Cache();
    Interlocked.Exchange(ref _foo, foo);
}
Run Code Online (Sandbox Code Playgroud)

编辑:

@Servy提供了一个更简单,自包含的复制品

public class Worker
{
    private static int foo;
    private static async void DoWork()
    {
        DoNothing(ref foo, await Task.FromResult(0));
    }

    private static void DoNothing(ref int item, int other)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)