我有一个IObservable
每秒生成一个值,然后是一个运行可能需要一些时间的代码的选择:
var events = Observable.Interval(TimeSpan.FromSeconds(1));
ssoInfoObservable = events
.Select(async e =>
{
Console.Out.WriteLine("Select : " + e);
await Task.Delay(4000);
return e;
})
.SelectMany(t => t.ToObservable())
.Subscribe(l => Console.WriteLine("Subscribe: " + l));
在我的示例中,长时间运行的操作需要4秒。当Select
中的代码正在运行时,我不希望生成Interval
中的其他值。我该如何做到这一点?这可能吗?也许使用特定的IScheduler
实现?
请注意,如果没有异步代码,则所有内容都按照here所述的预期工作。
此问题与one I asked earlier非常相似,但async/await
除外。
答案 0 :(得分:1)
请参阅此示例,了解如何创建async generate function。你需要一个时间偏移,而你不需要iterate
,因此看起来会更像这样:
public static IObservable<T> GenerateAsync<T>(TimeSpan span,
Func<int, Task<T>> generator,
IScheduler scheduler = null)
{
scheduler = scheduler ?? Scheduler.Default;
return Observable.Create<T>(obs =>
{
return scheduler.Schedule(0, span, async (idx, recurse) =>
{
obs.OnNext(await generator(idx));
recurse(idx + 1, span);
});
});
}
用法:
Extensions.GenerateAsync(TimeSpan.FromSeconds(1), idx => /*Async work, return a task*/, scheduler);
作为可能的第二个选项,您可以将switchFirst
的实现移植到C#中。 SwitchFirst
将订阅它收到的第一个Observable,并忽略后续的Observable直到其当前订阅完成。
如果你采用这种方法,你可能会有:
Observable.Interval(TimeSpan.FromSeconds(1))
.Select(e => Observable.FromAsync(() => /*Do Async stuff*/)
.SwitchFirst()
.Subscribe();