异步迭代器任务<IEnumerable >

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

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

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

听起来你可能正在寻找的东西就像IObservable ,它有点像基于推送的异步IEnumerable 。 请参阅Microsoft Open Technologies的Rex Extensions,即来自Microsoft Open Technologies的许可代码(Apache-2.0下许可的代码)(无联属关系), IObservable方法适用于IObservable ,使其像LINQ-to-Objects一样工作。

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

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

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

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

这是一个例子:

 var observable = Observable.Create(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()); 

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

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