我想要写函数,它将异步返回项目:
public static async Task<IEnumerable<T>> GetItems()
{
while (await ShouldLoopAsync())
{
yield return await GetItemAsync();
}
}
当然不会起作用。他们在1中提出了下一个解决方案:
return Observable.Create<T>(
observer => Task.Run(async () =>
{
while (await ShouldLoopAsync())
{
observer.OnNext(await getAsync());
}
observer.OnCompleted();
}
)
);
我不喜欢1接受的解决方案,因为它使用Observable.Create中的Task.Run方法。我想要一些具有反应性扩展的解决方案,该解决方案可以在当前TaskScheduler上运行,而不使用现有线程以外的其他线程。 我可以使用.net事件以声明的方式编写此类解决方案,但不能使用Rx。
更新
我试图删除Task.Run
并编写下一个测试:
[TestClass]
public class ReactiveWithTaskIEnumerable
{
[TestMethod]
public void ReactibeShouldProcessValuesWithoutnakoplenie()
{
Trace.WriteLine($"Start Thread {Thread.CurrentThread.ManagedThreadId}");
var i = GetIntsAsync()
.Subscribe(
onNext: p =>
{
Trace.WriteLine($"onNext Thread {Thread.CurrentThread.ManagedThreadId} {p}");
},
onCompleted: () =>
{
Trace.WriteLine($"onCompleted Thread {Thread.CurrentThread.ManagedThreadId}");
},
onError: p =>
{
Trace.WriteLine($"onError Thread {Thread.CurrentThread.ManagedThreadId} {p}");
throw p;
}
);
Trace.WriteLine($"Finish Thread {Thread.CurrentThread.ManagedThreadId}");
}
private IObservable<int> GetIntsAsync()
{
return Observable.Create<int>(
observer => async () =>
{
Trace.WriteLine($"Produce {Thread.CurrentThread.ManagedThreadId}");
try
{
foreach (var i in Enumerable.Range(1, 10))
{
await Task.Delay(1000);
observer.OnNext(1);
}
}
catch (Exception e)
{
observer.OnError(e);
}
observer.OnCompleted();
});
}
}
输出为:
Start Thread 3
Finish Thread 3
因此内部任务根本不会启动。
此后,我将GetIntsAsync
更改为此:
private IObservable<int> GetIntsAsync()
{
return Observable.Create<int>(
observer =>
{
async Task Lambda()
{
Trace.WriteLine($"Produce {Thread.CurrentThread.ManagedThreadId}");
try
{
foreach (var i in Enumerable.Range(1, 10))
{
await Task.Delay(1000);
observer.OnNext(1);
}
}
catch (Exception e)
{
observer.OnError(e);
}
observer.OnCompleted();
}
return Lambda();
});
}
这给出了下一个输出:
Debug Trace:
Start Thread 3
Produce 3
Finish Thread 3
与Task.Run
接近输出:
调试跟踪: 启动线程3 产生9 完成线程3
现在我需要等到可观察到的完成为止
答案 0 :(得分:2)
去NuGetting“ System.Interactive”,然后尝试一下:
public static IEnumerable<int> GetItems()
{
return EnumerableEx.Create<int>(async y =>
{
while (await ShouldLoopAsync())
{
await y.Return(GetItemAsync());
}
await y.Break();
});
}