C# 订户丢失了消息;这是Rx的错误还是我做错了?

C# 订户丢失了消息;这是Rx的错误还是我做错了?,c#,wpf,system.reactive,reactive-programming,C#,Wpf,System.reactive,Reactive Programming,我有一个带有以下构造函数的单窗口WPF应用程序 numbers = Observable.Generate(DateTime.Now, time => true, time => DateTime.Now, time =>

我有一个带有以下构造函数的单窗口WPF应用程序

        numbers = Observable.Generate(DateTime.Now,
                                         time => true,
                                         time => DateTime.Now,
                                         time => { return new     Random(DateTime.Now.Millisecond).NextDouble() * 99 + 2; },
                                         time => TimeSpan.FromSeconds(1.0));


        numbers.ObserveOnDispatcher()
            .Subscribe(s => list1.Items.Add(s.ToString("##.00")));

        numbers.Where(n => n < 10).ObserveOnDispatcher().
            Subscribe(s => list2.Items.Add(s.ToString("##.00")));
numbers=Observable.Generate(DateTime.Now),
时间=>正确,
时间=>DateTime。现在,
time=>{returnnewrandom(DateTime.Now.毫秒).NextDouble()*99+2;},
时间=>TimeSpan.FromSeconds(1.0));
number.ObserveOnDispatcher()
.Subscribe(s=>list1.Items.Add(s.ToString(“##.00”));
其中(n=>n<10).ObserveOnDispatcher()。
订阅(s=>list2.Items.Add(s.ToString(“##.00”));
现在这里是列表的屏幕截图-请注意,左侧列表中缺少3.76。。。这种行为是间歇性的


简单的回答是你做错了。Rx工作正常

当您创建一个可观察对象时,您创建的是随时间变化的值序列的定义,而不是随时间变化的值的实际序列。这意味着,每当您有一个可观察对象的订户时,您都在为每个订户创建可观察对象的新实例

因此,在您的案例中,有两个此序列的实例正在运行:

var numbers =
    Observable
        .Generate(
            DateTime.Now,
            time => true,
            time => DateTime.Now,
            time => new Random(DateTime.Now.Millisecond)
                .NextDouble() * 99 + 2,
            time => TimeSpan.FromSeconds(1.0));
现在,由于您立即连续两次订阅此可观察对象,此可观察对象的两个实例将尝试几乎同时生成值。因此,值
DateTime.Now.millissecond
在大多数情况下都是相同的,但现在总是相同的。对于相同的
x
,从
new Random(x).NextDouble()
返回的值是相同的,因此,为什么大多数情况下,从可观察对象的两个实例中获得相同的值。当
DateTime.Now.millis秒
不同时,您会得到两个不同的值,并且订阅者似乎缺少值


下面是一个替代版本,它应该可以按照您最初的预期工作:

var rnd = new Random((int)DateTime.Now.Ticks);

var numbers =
    Observable
        .Generate(0, n => true, n => 0,
            n => rnd.NextDouble() * 99 + 2,
            n => TimeSpan.FromSeconds(1.0));

var publishedNumbers = numbers.Publish();

publishedNumbers
    .ObserveOnDispatcher()
    .Subscribe(s => list1.Items.Add(s.ToString("##.00")));

publishedNumbers
    .Where(n => n < 10)
    .ObserveOnDispatcher()
    .Subscribe(s => list2.Items.Add(s.ToString("##.00")));

publishedNumbers.Connect();
var rnd=new Random((int)DateTime.Now.Ticks);
变量数=
可观察
.Generate(0,n=>true,n=>0,
n=>rnd.NextDouble()*99+2,
n=>TimeSpan.FromSeconds(1.0));
var publishedNumbers=numbers.Publish();
出版编号
.ObserveOnDispatcher()
.Subscribe(s=>list1.Items.Add(s.ToString(“##.00”));
出版编号
.其中(n=>n<10)
.ObserveOnDispatcher()
.Subscribe(s=>list2.Items.Add(s.ToString(“##.00”));
publishedNumber.Connect();

简单的回答是你做错了。Rx工作正常

当您创建一个可观察对象时,您创建的是随时间变化的值序列的定义,而不是随时间变化的值的实际序列。这意味着,每当您有一个可观察对象的订户时,您都在为每个订户创建可观察对象的新实例

因此,在您的案例中,有两个此序列的实例正在运行:

var numbers =
    Observable
        .Generate(
            DateTime.Now,
            time => true,
            time => DateTime.Now,
            time => new Random(DateTime.Now.Millisecond)
                .NextDouble() * 99 + 2,
            time => TimeSpan.FromSeconds(1.0));
现在,由于您立即连续两次订阅此可观察对象,此可观察对象的两个实例将尝试几乎同时生成值。因此,值
DateTime.Now.millissecond
在大多数情况下都是相同的,但现在总是相同的。对于相同的
x
,从
new Random(x).NextDouble()
返回的值是相同的,因此,为什么大多数情况下,从可观察对象的两个实例中获得相同的值。当
DateTime.Now.millis秒
不同时,您会得到两个不同的值,并且订阅者似乎缺少值


下面是一个替代版本,它应该可以按照您最初的预期工作:

var rnd = new Random((int)DateTime.Now.Ticks);

var numbers =
    Observable
        .Generate(0, n => true, n => 0,
            n => rnd.NextDouble() * 99 + 2,
            n => TimeSpan.FromSeconds(1.0));

var publishedNumbers = numbers.Publish();

publishedNumbers
    .ObserveOnDispatcher()
    .Subscribe(s => list1.Items.Add(s.ToString("##.00")));

publishedNumbers
    .Where(n => n < 10)
    .ObserveOnDispatcher()
    .Subscribe(s => list2.Items.Add(s.ToString("##.00")));

publishedNumbers.Connect();
var rnd=new Random((int)DateTime.Now.Ticks);
变量数=
可观察
.Generate(0,n=>true,n=>0,
n=>rnd.NextDouble()*99+2,
n=>TimeSpan.FromSeconds(1.0));
var publishedNumbers=numbers.Publish();
出版编号
.ObserveOnDispatcher()
.Subscribe(s=>list1.Items.Add(s.ToString(“##.00”));
出版编号
.其中(n=>n<10)
.ObserveOnDispatcher()
.Subscribe(s=>list2.Items.Add(s.ToString(“##.00”));
publishedNumber.Connect();


“这是Rx的一个bug还是我做错了?”-你在给赔率吗?我只是在问一个问题。可能性肯定对我不利。图像似乎是一个断开的链接。我可以很好地查看它,您的浏览器/计算机可能会阻止来自您正在浏览的网站以外的其他网站的图像。这是公司网络屏蔽的URL。“这是Rx的错误还是我做错了?”-你在给赔率吗?我只是问个问题。可能性肯定对我不利。图像似乎是一个断开的链接。我可以很好地查看它,您的浏览器/计算机可能会阻止来自您正在浏览的网站以外的其他网站的图像。这是URL,似乎是公司网络阻止了它。很好的观察。谢谢分享。你让我的一天。。。我将代码改为使用秒而不是毫秒,现在我再也看不到这个问题了。@fahadash-将它改为秒并不能解决这个问题,只会使它的可能性降低1000倍。然后你就不能正确地产生随机数了。您需要重构可观察对象,并可能使用
Publish
来共享可观察对象。@fahadash-我为您添加了一个替代解决方案,该解决方案的行为应该与您最初期望的一样……我认为数字序列可以进一步缩减为
observable.Interval(TimeSpan.FromSeconds(1.0))。选择(=>rnd.NextDouble()*99+2)
。我认为这更具表现力,即每秒从这个序列中投射一个随机数。很好的观察。谢谢分享。你让我的一天。。。我将代码改为使用秒而不是毫秒,现在我再也看不到这个问题了。@fahadash-将它改为秒并不能解决这个问题,它只是使