c# async-await interlocked compiler-bug

El uso de await dentro de Interlocked.Exchange bloquea el compilador de C#



async-await compiler-bug (0)

Ignore por un momento el absurdo de await una llamada de Enumerable.Range . Solo está ahí para provocar el comportamiento crash-y. Con la misma facilidad podría ser un método que está haciendo un IO de red para construir una colección de objetos de valor. (De hecho, aquí fue donde vi que ocurría el accidente).

Si comento fuera de la línea Interlocked.Exchange , el compilador no se bloquea.

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

Cambiar RefreshCache() a esto evita que el compilador se bloquee:

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

Editar:

Una reproducción aún más simple y autónoma proporcionada por @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) { } }