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
异步(在这种情况下,这不是解决您的底层问题,尽管它会使您的代码编译).
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中.
据我了解,这可能随时更改.