当所有可观察到的异步项都已完成处理时,如何运行Final()?

时间:2019-10-28 16:30:23

标签: c# linq async-await system.reactive

为了使UI更具响应性,我分批输出项目。这里的问题是,OnFinally()在最后一个OutputItems()完成之前被调用。

    IObservable<IList<xx>> obs = Observable
     .Interval(TimeSpan.FromSeconds(.1), Scheduler.Default)
       .Zip(dirEnum.ToObservable(NewThreadScheduler.Default)
         .Buffer(100), (a, b) => b)
     .ObserveOn(syncContext).Finally(OnFinally);
    ...
    obs.Subscribe(async x => await OutputItems(x));

所有物品都售完后,有没有办法打电话给OnFinally?

2 个答案:

答案 0 :(得分:1)

将缓冲区直接投影到您的OutPutItems上,不要在Subscription内部使用await

IObservable<IList<xx>> obs = Observable
     .Interval(TimeSpan.FromSeconds(.1), Scheduler.Default)
       .Zip(dirEnum.ToObservable(NewThreadScheduler.Default)
         .Buffer(100), (a, b) => b)
     .ObserveOn(syncContext).Finally(OnFinally)
     .SelectManay(X=>OutputItmes().ToObservable())
     .Finally(OnFinally);
    ...
    obs.Subscribe();

答案 1 :(得分:0)

Subscribe方法不接受异步委托,因此您的lambda是异步无效的。异步void方法是不可观察或等待的,并且它们的异常也不可捕获(它们未处理并导致进程崩溃)。一种解决方案是将您的批次投影到Task个批次中,然后使用Merge方法返回到批次中。 Subscribe结束时,您将以任务完成的顺序(可能不是其原始顺序)获得任务的结果。如果您对结果不感兴趣,只需不加任何参数即可调用Subscribe

IObservable<IList<xx>> obs = Observable
    .Interval(TimeSpan.FromSeconds(.1), Scheduler.Default)
    .Zip(dirEnum.ToObservable(NewThreadScheduler.Default)
    .Buffer(100), (a, b) => b)
    .Select(x => OutputItemsAsync(x))
    .Merge()
    .ObserveOn(syncContext)
    .Finally(OnFinally);

obs.Subscribe();