IAsyncEnumerable not working in C# 8.0 preview

前端 未结 2 1164
温柔的废话
温柔的废话 2021-02-20 11:40

I was playing around with C# 8.0 preview and can\'t get IAsyncEnumerable to work.

I tried the following

<         


        
2条回答
  •  深忆病人
    2021-02-20 12:31

    That's a bug in the compiler that can be fixed by adding a few lines of code found here :

    namespace System.Threading.Tasks
    {
        using System.Runtime.CompilerServices;
        using System.Threading.Tasks.Sources;
    
        internal struct ManualResetValueTaskSourceLogic
        {
            private ManualResetValueTaskSourceCore _core;
            public ManualResetValueTaskSourceLogic(IStrongBox> parent) : this() { }
            public short Version => _core.Version;
            public TResult GetResult(short token) => _core.GetResult(token);
            public ValueTaskSourceStatus GetStatus(short token) => _core.GetStatus(token);
            public void OnCompleted(Action continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) => _core.OnCompleted(continuation, state, token, flags);
            public void Reset() => _core.Reset();
            public void SetResult(TResult result) => _core.SetResult(result);
            public void SetException(Exception error) => _core.SetException(error);
        }
    }
    
    namespace System.Runtime.CompilerServices
    {
        internal interface IStrongBox { ref T Value { get; } }
    }
    
    

    As Mads Torgersen explains in Take C# 8 for a spin :

    But if you try compiling and running it, you get an embarassing number of errors. That’s because we messed up a bit, and didn’t get the previews of .NET Core 3.0 and Visual Studio 2019 perfectly aligned. Specifically, there’s an implementation type that async iterators leverage that’s different from what the compiler expects.

    You can fix this by adding a separate source file to your project, containing this bridging code. Compile again, and everything should work just fine.

    Update

    Looks there's another bug when Enumerable.Range() is used inside the async iterator.

    The GetNumbersAsync() method in the issue ends after only two iterations :

    static async Task Main(string[] args)
    {
        await foreach (var num in GetNumbersAsync())
        {
            Console.WriteLine(num);
        }
    }
    
    private static async IAsyncEnumerable GetNumbersAsync()
    {
        var nums = Enumerable.Range(0, 10);
        foreach (var num in nums)
        {
            await Task.Delay(100);
            yield return num;
        }
    }
    

    This will print only :

    0
    1
    

    This won't happen with an array or even another iterator method:

    private static async IAsyncEnumerable GetNumbersAsync()
    {
        foreach (var num in counter(10))
        {
            await Task.Delay(100);
            yield return num;
        }
    }
    
    private static IEnumerable counter(int count)
    {
        for(int i=0;i

    This will print the expected :

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    

    Update 2

    Seems that's a know bug as well: Async-Streams: iteration stops early on Core

    提交回复
    热议问题