【发布时间】:2016-06-15 19:44:56
【问题描述】:
如果我有一个 INPC 支持类 Numbers 具有两个属性 A 和 B。我可以写这样的代码
Numbers numbers = new Numbers();
IObservable<double> o = numbers.WhenAnyValue(p=>p.A,p=>p.B,(a,b)=>a/b);
WhenAnyValue 是 ReactiveUI 库中的一种实用方法,用于从属性更改事件组合 observables。如果我再写。
o.Subscribe(v=>Console.WriteLine(v));
只要 A 或 B 发生变化,它就会打印 a/b。在我设置之前这一切都很好
numbers.B = 0;
现在 a/b 将抛出 DivideByZeroException 并且 observable 将终止。然而,这是一个 UI。我不希望 observable 终止。我只是希望忽略异常或记录它并继续。第一次尝试是查看 IObservable 包含一个名为 Retry 的扩展方法,该方法将在异常后重新连接到 observable。我们尝试
Numbers numbers = new Numbers();
IObservable<double> o = numbers
.WhenAnyValue(p=>p.A,p=>p.B,(a,b)=>a/b)
.Retry();
o.Subscribe(v=>Console.WriteLine(v));
但是,当我执行 numbers.B = 0 时,Retry 将忽略异常并重新连接,并且会立即一次又一次地失败,因为 WhenAnyValue 总是传递一个事件订阅。
所以看来我需要的是重试,它会在重新连接后忽略第一个输入 iff 它与导致断开第一个输入的错误的输入相同,除了我不认为RX 可以做到这一点。
有什么想法吗?
完整的测试用例
以下测试用例不会终止。
public class Numbers : ReactiveObject
{
int _A;
public int A
{
get { return _A; }
set { this.RaiseAndSetIfChanged(ref _A, value); }
}
int _B;
public int B
{
get { return _B; }
set { this.RaiseAndSetIfChanged(ref _B, value); }
}
}
[Fact]
public void TestShouldTerminate()
{
var numbers = new Numbers();
var o = numbers
.WhenAnyValue(p => p.A, p => p.B, Tuple.Create)
.Select(v=>v.Item1/v.Item2)
.Select(v=>v+1)
.Retry();
double value = 0;
o.Subscribe(v => value = v);
numbers.A = 10;
numbers.B = 20;
value.Should().Be(1.5);
}
}
}
}
【问题讨论】:
-
您可以添加
.Where(t => t.Item2 != 0)子句。或者你可以将你的部门包装在 Observable 操作中,这样Retry得到OnError并重新订阅。
标签: c# .net exception system.reactive reactiveui