我有这个简单的代码,其中:
以下是代码:
private void DisplayPoints()
{
var x = 0;
var ob = this.GeneratePoints();
ob
.Sample(TimeSpan.FromMilliseconds(500))
.SubscribeOn(ThreadPoolScheduler.Instance)
.ObserveOn(SynchronizationContext.Current)
.Subscribe(d => Console.WriteLine(d));
}
private IObservable<double> GeneratePoints()
{
return Observable.Create<double>(o => this.GeneratePoints(o));
}
private IDisposable GeneratePoints(IObserver<double> observer)
{
var i = 0;
while (true)
{
var value = random.Next(0, 100) * (1 / (double)random.Next(1, Math.Min(50, Math.Max(i, 1))));
observer.OnNext(value);
i++;
}
return Disposable.Empty;
}
但是,控制台上没有输出任何内容(即永远不会调用匿名观察者)。如果我删除Sample
运算符,则会调用observer,尽管这种行为显然不是预期的(UI线程会被轰炸)。
我显然在这里遗漏了一些东西。我的目的是生成数据,通过IObserver推送数据,并通过UI显示一些数据。
编辑,因为有些人误解了我的意图(尽管上面已明确说过),我应该重申,我正在努力做的事情:
double
值似乎足以解决我的问题)使用IObservable
和Reactive Extensions似乎是解决我问题的好方法。
重复:我 不会在实际代码中返回随机数 - 这只是占位符让我的预期行为发挥作用。
答案 0 :(得分:1)
我怀疑您的问题与Throttle
在内部通过DefaultScheduler.Instance
引入并发并且IDisposable GeneratePoints(IObserver<double> observer)
的实现是非标准的事实有关。
尝试像这样重新实现IObservable<double> GeneratePoints()
:
private IObservable<double> GeneratePoints()
{
return Observable.Generate<int, double>(
0,
i => true,
i => i + 1,
i => random.Next(0, 100) * (1 / (double)random.Next(1, Math.Min(50, Math.Max(i, 1)))));
}
这可能会有所帮助。
问题来自您的observable在订阅过程中直接推出值。在创建observable时,应始终尝试使用标准的内置运算符。上面的代码使用内置的Generate
运算符,因此它应该可以更好地使用您的代码。
答案 1 :(得分:1)
您可能不希望在紧密循环中生成随机数。最好使用时间间隔。下面每200毫秒产生一次随机数。
IObservable<double> observable =
Observable.Interval(TimeSpan.FromMillSeconds(200))
.Select((t,i) => random.Next(0, 100)
* (1 / (double)random.Next(1, Math.Min(50, Math.Max(i, 1)))))
Enigmativity为您编写的代码也是有效的紧密循环。他对你在订阅过程中推出值的错误提出的观点也是正确的。您必须对代码进行的最小更改才能使其正常工作。
private static Task GeneratePoints(IObserver<double> observer, CancellationToken token)
{
return Task.Run(() =>
{
var i = 0;
var random = new Random();
while ( true )
{
token.ThrowIfCancellationRequested();
var value = random.Next(0, 100) * ( 1 / ( double ) random.Next(1, Math.Min(50, Math.Max(i, 1))) );
observer.OnNext(value);
i++;
}
});
}
稍后
Observable.Create<double>((observer, token) => GeneratePoints(observer, token));
请注意要传递的取消令牌。当序列的订阅者取消订阅时,将设置此令牌并且循环将终止。
然而,这是一项很多工作,而且Enigmativities的答案更简单,并为您提取上述代码。了解如何针对更复杂的情况手动执行此操作仍然很有用。
答案 2 :(得分:0)
Throttle
只会在存在至少500毫秒(在您的情况下)的间隙时通过值。由于GeneratePoints
推动价值远远超过此速度,所以不会发生任何事情。 Sample
可能是您想要的运算符,在这种情况下,它将每500毫秒生成一个值。
Source: 1111111111111111111----------111---111111
Throttle (5): -----------------------1-----------------
Sample (5): ----1----1----1----1---1------------1----1