我试图实现一个返回迭代器的异步函数。代码如下:
private async Task<IEnumerable<char>> TestAsync(string testString)
{
foreach (char c in testString.ToCharArray())
{
// do other work
yield return c;
}
}
但是,有一个错误消息,该函数不能是迭代器块,因为Task<IEnumerable<char>>
它不是迭代器接口类型。有解决方案吗?
这听起来像你可能真正在寻找的是类似的东西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;
}
}
如果不知道异步实际做了什么,可能有更好的方法来实现你的目标。
为了详细说明以前的答案,你可以使用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());