首页 > 解决方案 > IAsyncEnumerable 在 C# 8.0 预览版中不起作用

问题描述

我正在玩 C# 8.0 预览版,但无法开始IAsyncEnumerable工作。

我尝试了以下

public static async IAsyncEnumerable<int> Get()
{
    for(int i=0; i<10; i++)
    {
        await Task.Delay(100);
        yield return i;
    }
}

我最终使用了一个名为 的 Nuget 包AsyncEnumerator,但出现以下错误:

  1. 错误 CS1061“ IAsyncEnumerable<int>”不包含“”的定义,并且找不到接受第一个“”类型参数的GetAwaiter可访问扩展方法“ ” (您是否缺少 using 指令或程序集引用?)GetAwaiterIAsyncEnumerable<int>
  2. 错误 CS1624“”的主体Program.Get()不能是迭代器块,因为“ IAsyncEnumerable<int>”不是迭代器接口类型

我在这里想念什么?

标签: c#c#-8.0iasyncenumerable

解决方案


这是编译器中的一个错误,可以通过在此处添加几行代码来修复:

namespace System.Threading.Tasks
{
    using System.Runtime.CompilerServices;
    using System.Threading.Tasks.Sources;

    internal struct ManualResetValueTaskSourceLogic<TResult>
    {
        private ManualResetValueTaskSourceCore<TResult> _core;
        public ManualResetValueTaskSourceLogic(IStrongBox<ManualResetValueTaskSourceLogic<TResult>> 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<object> 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<T> { ref T Value { get; } }
}

正如 Mads Torgersen 在Take C# 8 for a spin中解释的那样:

但是如果你尝试编译和运行它,你会得到一个令人尴尬的错误数量。那是因为我们有点搞砸了,没有让 .NET Core 3.0 和 Visual Studio 2019 的预览完全一致。具体来说,异步迭代器利用的实现类型与编译器所期望的不同。

您可以通过将包含此桥接代码的单独源文件添加到项目中来解决此问题。再次编译,一切正常。

更新

Enumerable.Range()看起来在异步迭代器中使用时还有另一个错误。

问题中的GetNumbersAsync()方法仅在两次迭代后结束:

static async Task Main(string[] args)
{
    await foreach (var num in GetNumbersAsync())
    {
        Console.WriteLine(num);
    }
}

private static async IAsyncEnumerable<int> GetNumbersAsync()
{
    var nums = Enumerable.Range(0, 10);
    foreach (var num in nums)
    {
        await Task.Delay(100);
        yield return num;
    }
}

这将只打印:

0
1

数组甚至其他迭代器方法都不会发生这种情况:

private static async IAsyncEnumerable<int> GetNumbersAsync()
{
    foreach (var num in counter(10))
    {
        await Task.Delay(100);
        yield return num;
    }
}

private static IEnumerable<int> counter(int count)
{
    for(int i=0;i<count;i++)
    {
        yield return i;
    }
}

这将打印预期的:

0
1
2
3
4
5
6
7
8
9

更新 2

似乎这也是一个已知的错误: Async-Streams:迭代在 Core 上提前停止


推荐阅读