异步迭代器任务<IEnumerable <T >>

use*_*923 30 .net c# clr iterator asynchronous

我正在尝试实现一个返回迭代器的异步函数.这个想法如下:

    private async Task<IEnumerable<char>> TestAsync(string testString)
    {
        foreach (char c in testString.ToCharArray())
        {
            // do other work
            yield return c;
        }
    }
Run Code Online (Sandbox Code Playgroud)

但是,有一个错误消息,该函数不能是迭代器块,因为Task<IEnumerable<char>>它不是迭代器接口类型.有解决方案吗?

Joe*_*nta 23

这听起来像你真正想要的东西IObservable<T>,有点像基于推送的异步IEnumerable<T>.参见Reactive Extensions,又名来自Microsoft Open Technologies的Rx(在Apache-2.0下获得许可的代码)(无联属关系),可以使用大量方法IObservable<T>使其像LINQ-to-Objects一样工作.

问题IEnumerable<T>在于没有什么能真正使枚举本身异步.如果您不想在Rx上添加依赖项(这实际上是什么使得IObservable<T>闪耀),这个替代方案可能对您有用:

public async Task<IEnumerable<char>> TestAsync(string testString)
{
    return GetChars(testString);
}

private static IEnumerable<char> GetChars(string testString)
{
    foreach (char c in testString.ToCharArray())
    {
        // do other work
        yield return c;
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然我想指出,如果不知道实际上异步完成了什么,可能会有更好的方法来实现你的目标.您发布的代码中没有一个实际上会异步执行任何操作,而且我真的不知道是否有任何// do other work异步(在这种情况下,这不是解决您的底层问题,尽管它会使您的代码编译).

  • 现在,您可以使用[IAsyncEnumerable](https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.generic.iasyncenumerable-1?view=netcore-3.0)。它随C#8 .Net Core 3.0或通过Nuget一起提供。 (3认同)

Joh*_*zen 15

要详细说明以前的答案,您可以使用Reactive Extensions的Observable.Create<TResult>一系列方法来完成您想要的操作.

这是一个例子:

var observable = Observable.Create<char>(async (observer, cancel) =>
{
    for (var i = 0; !cancel.IsCancellationRequested && i < 100; i++)
    {
        observer.OnNext(await GetCharAsync());
    }
});
Run Code Online (Sandbox Code Playgroud)

以下是如何在LINQPad中使用它,例如:

// Create a disposable that keeps the query running.
// This is necessary, since the observable is 100% async.
var end = Util.KeepRunning();

observable.Subscribe(
    c => Console.WriteLine(c.ToString()),
    () => end.Dispose());
Run Code Online (Sandbox Code Playgroud)


Joe*_*nta 10

包括语言支持在内的更多"包含电池"的实现目前(在撰写本文时)被考虑包含在C#8.0中.

据我了解,这可能随时更改.

  • 异步流问题的特定URL是:https://github.com/dotnet/csharplang/issues/43 (2认同)