执行劣质 ReactiveCommand 时,ReactiveUI 处理异常的方式是什么?

Jon*_*ois 3 c# wpf reactiveui

这是我试图演示的(过度)简化版本:

var reactiveCommandA = ReactiveCommand.CreateAsyncTask(_ => CanPossiblyThrowAsync());
reactiveCommandA.ThrownExceptions
                .Subscribe(ex => UserError.Throw("Oh no A", ex));

var reactiveCommandB = ReactiveCommand.CreateAsyncTask(_ => CanAlsoPossiblyThrowAsync());
reactiveCommandB.ThrownExceptions
                .Subscribe(ex => UserError.Throw("Oh no B", ex));

var reactiveCommandC = ReactiveCommand.CreateAsyncTask
   (
     async _ =>
               {
                 await reactiveCommandA.ExecuteAsync(); // <= Could throw here
                 await reactiveCommandB.ExecuteAsync();
                 DoSomethingElse();
               }
    );

reactiveCommandC.ThrownExceptions
                .Subscribe(ex => UserError.Throw("Oh no C", ex));
Run Code Online (Sandbox Code Playgroud)

因此,假设我的后台实现reactiveCommandA可能会引发异常。没关系,因为我已经订阅.ThrownExceptions并且理论上会通知用户并重试/失败/中止(为简洁起见,此处未显示)。所以它不会冒泡给调度员。

所以当reactiveCommandA它自己执行时就很棒了。但是,我有reactiveCommandCwhich 执行reactiveCommandAreactiveCommandB。我也订阅了它的.ThrownExceptions。我遇到的问题是,如果我执行reactiveCommandCreactiveCommandA在其中抛出实现,它也会导致reactiveCommandC爆炸。然后我会两次通知用户相同的根错误,因为先做reactiveCommandA它的.ThrownExceptions事情,然后reactiveCommandC再做它的.ThrownExceptions事情。

那么对于这种情况有标准的方法吗?最好是一些优雅的东西,因为我发现现有的代码相当干净,我不想让事情变得混乱或引入意大利面条。

我想到的事情:

  • 用块包围“await...”行try/catch并吞咽异常并退出。如果我必须做很多事情,那就太丑了。

  • 尽管await reactiveCommandA.ExecuteAsync().Catch(Observable.Never<Unit>());我认为这会导致reactiveCommandC永远无法完成,所以它永远无法再次执行。

  • 使用与该.Catch()方法相同的方法,但根据我是否成功通过返回一个布尔值(例如.Catch(Observable.Return(false))。仍然需要检查我们是否可以在每个await语句之间继续。

这里还有更圆滑的事可做吗?谢谢。

Ana*_*tts 5

嗯,这是 ReactiveCommand 设计的一个方面,有点糟糕(披露:我可以说它很糟糕,我写了它!)这是修复它的懒惰方法:

Observable.Merge(rxCmdA.ThrownExceptions, rxCmdB.ThrownExceptions, rxCmdC.ThrownExceptions)
    .Throttle(TimeSpan.FromMilliseconds(250), RxApp.MainThreadScheduler)
    .Subscribe(ex => UserError.Throw("Oh no C", ex));
Run Code Online (Sandbox Code Playgroud)

将来我肯定想修复一些此类双掷问题,以及有关 RxCmd 设计的其他一些问题。