【发布时间】:2018-05-10 04:41:05
【问题描述】:
我有以下可观察序列
int num = 0;
var o = Observable.Create<int>(observer => Task.Run(() =>
{
var rnd = new Random((int)DateTime.Now.Ticks);
Console.WriteLine($"Starting subscription loop # {++num}");
for (int i=0;i<100;i++)
{
Thread.Sleep(200);
if (i == 3)
{
observer.OnError(new ApplicationException("test exception"));
break;
}
observer.OnNext(rnd.Next(0, 50));
}
})).Publish().RefCount();
以及以下通知处理程序
o
.Retry()
.Subscribe(Console.WriteLine, ex => Console.WriteLine($"Exception occurred: {ex.Message}"), () => Console.WriteLine("Completed"));
这是我的输出
Starting subscription loop # 1
47
27
12
Starting subscription loop # 2
Starting subscription loop # 3
Starting subscription loop # 4
Starting subscription loop # 5
Starting subscription loop # 6
Starting subscription loop # 7
Starting subscription loop # 8
Starting subscription loop # 9
...
我在Lee Campbell's IntroToRx book 中阅读了以下内容
如果您预计您的序列会遇到可预测的问题, 您可能只是想重试。一个这样的例子,当你想 重试是在执行 I/O 时(例如 Web 请求或磁盘访问)。输入输出 因间歇性故障而臭名昭著。重试扩展方法 提供重试失败指定次数的能力,或 直到成功。
我在样本中注意到的行为与坎贝尔指出的行为不符,也不符合他的样本。我错过了什么?
如果我不Publish().RefCount(),它可以正常工作。
【问题讨论】:
-
new Random((int)DateTime.Now.Ticks)是一种浪费,因为new Random()在幕后就是这样做的。你最好创建一个[ThreadStatic]静态字段变量。 -
@Enigmativity No it does not 它使用的逻辑涉及两个
Random对象一个循环一个维护。 -
有趣。我想知道什么时候改变了。尽管如此,使用
new Random((int)DateTime.Now.Ticks)而不是new Random()并没有什么不同。它仍然存在同样的坏种子问题。 -
相关:How to fix the inconsistency of the Publish().RefCount() behavior? TL;DR,您观察到的问题行为无法可靠修复。您
Publish的原因是为了确保多个订阅者会收到来自同一序列的通知。这只能通过有状态的Subject(记住源的完成状态)备份的Publish来保证。可悲的后果是Publish不可重复使用。只能连接一次。
标签: c# system.reactive