C#如何重新启动RX订阅

时间:2017-04-22 18:14:53

标签: c# wpf system.reactive

假设我们有这个可观察序列(RX)和匹配订阅:

var behaviorSubject = new BehaviorSubject<int>(3);
var sequence = behaviorSubject.Select(x => this.webservice.Call(x)).Switch();
var subscription = this.sequence.Subscribe(this.Subject.OnNext, this.OnSequenceFaulted);

序列用于在每次behaviorSubject发出新值时执行Web服务调用,同时取消先前的请求。如果在Webservice调用期间发生异常,则将终止订阅(在调用OnSequenceFaulted方法之后)。

这样实施OnSequenceFaulted方法是一种好习惯吗?我们是否需要重新启动(重新分配)sequence以及订阅,因为异常来自sequence中的可观察对象?是否需要明确处理故障订阅?

public void OnSequenceFaulted(Exception e)
{
    subscription?.Dispose();
    subscription = sequence.Subscribe(this.Subject.OnNext, this.OnSequenceFaulted);
}

1 个答案:

答案 0 :(得分:1)

就良好实践而言,这取决于您的用例以及如果webservice.Call抛出异常您想要发生什么。

为了解决你问题的具体部分,虽然围绕rx这里有一些很好的参考 Reactive Observable Subscription Disposal

  

如果observable完成 - 使用OnCompleted或OnError -   然后订阅已经为您处理。

introtorx在这里对各种错误处理技术以及您的场景中可能适用的内容进行了很好的描述

http://www.introtorx.com/content/v1.0.10621.0/11_AdvancedErrorHandling.html

至于如何处理您的特定场景,有几个选项,这里只是几个想法

  1. 你可以直接处理webcall本身的异常,这样它就不会将流转换为OnError http://www.introtorx.com/content/v1.0.10621.0/11_AdvancedErrorHandling.html#CatchSwallowingException

    var sequence = behaviorSubject.Select(x => this.webservice.Call(x)
              .Catch((Exception exc) => 
                   //do something with exception, 
                   //maybe just return an empty observable and log the exception
              ).Switch();
    
  2. 您也可以告诉它重试 http://www.introtorx.com/content/v1.0.10621.0/11_AdvancedErrorHandling.html#Retry

    var subscription = this.sequence.Retry().Subscribe(this.Subject.OnNext, this.OnSequenceFaulted);
    
  3. 并不是特定的Rx最佳实践AFAIK。如果发生异常,它实际上就是您想要发生的事情。如果你根本不在乎并希望它能继续存在,那么Retry就可以了。如果你想捕获并记录,那么你可以将catch放在webservice调用上。如果你想检查异常,然后有不同的异常导致不同的出现,你可以在webservice调用上添加不同的catch。