异步迭代任务 异步迭代任务 (Asynchronous iterator Task

2019-05-11 22:16发布

我想实现一个返回一个迭代异步函数。 我们的想法是以下几点:

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

但是,存在该函数不能是迭代器块,因为错误消息Task<IEnumerable<char>>是不迭代器接口类型。 有没有解决的办法?

Answer 1:

这听起来像你可能真的找的是类似IObservable<T>这是有点像基于推送的异步IEnumerable<T> 见无功扩展,又名的Rx (Apache的2.0许可的代码)(没有隶属关系),用于与工作方法的一个巨大的主机IObservable<T>使它象LINQ到对象和更多的工作。

这个问题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;
    }
}

但我想指出的是,不知道什么是真正被异步完成的,有可能是一个更好的方法来实现自己的目标。 你贴实际上将做任何事情异步的,我真的不知道,如果在任何代码的无// do other work是异步的(在这种情况下,这是不是你的潜在的问题,但它会让你的代码的解决方案编译)。



Answer 2:

为了详细说明以前的答案,你可以使用无扩展Observable.Create<TResult>家庭的方法做你想要什么。

下面是一个例子:

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

这里是你如何在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());


Answer 3:

一个更“电池-包括”实现这种事情,包括语言支持,目前(在写作的时间)被认为包含在C#8.0。

据我所知,这是可能随时改变。



文章来源: Asynchronous iterator Task>