我正在尝试模拟一种情况,即传感器读数每隔一秒钟触发一次。然后,我想收集最近三秒钟内发生的所有读数,最多不超过5个读数,并输出该列表。
这行不通,但我不明白为什么。
public static class Extensions
{
public static IObservable<IList<T>> SlidingBuffer<T>(this IObservable<T> obs, TimeSpan span, int max)
{
return Observable.Create<IList<T>>(cl =>
{
var acc = new List<T>();
return obs.Buffer(span)
.Subscribe(next =>
{
if (next.Count == 0) //no activity in time span
{
cl.OnNext(acc);
acc.Clear();
}
else
{
acc.AddRange(next);
if (acc.Count >= max) //max items collected
{
cl.OnNext(acc);
acc.Clear();
}
}
}, err => cl.OnError(err), () => { cl.OnNext(acc); cl.OnCompleted(); });
});
}
}
public class SensorReading
{
public int Time { get; set; }
public int Value { get; set; }
public override string ToString() => new { Time, Value }.ToString();
public override bool Equals(object obj) =>
obj is SensorReading other && this.Time == other.Time && this.Value == other.Value;
public override int GetHashCode() => Time.GetHashCode() ^ Value.GetHashCode();
}
public static class Program
{
public static void Main(string[] args)
{
var els = new EventLoopScheduler();
var dispatcher = new EventLoopScheduler();
var obs = SimulateLiveData()
.SlidingBuffer(new System.TimeSpan(3000), 5)
.SubscribeOn(els)
.ObserveOn(dispatcher)
.Select((sr) => DoCalc(sr))
.Subscribe();
}
public static IEnumerable<SensorReading> DoCalc(IEnumerable<SensorReading> sr)
{
sr.Dump(); // Dump is linqpad Dump
return sr;
}
private static readonly SensorReading[] HistoricData = new[]
{
new SensorReading { Time = 1, Value = 0 },
new SensorReading { Time = 2, Value = 20 },
new SensorReading { Time = 3, Value = 15 },
new SensorReading { Time = 4, Value = 30 },
new SensorReading { Time = 5, Value = 45 }, // Here we crossed the threshold upward
new SensorReading { Time = 6, Value = 50 },
new SensorReading { Time = 7, Value = 30 }, // Here we crossed downward. Note that the current query logic only detects upward swings.
new SensorReading { Time = 8, Value = 35 },
new SensorReading { Time = 9, Value = 60 }, // Here we crossed upward again
new SensorReading { Time = 10, Value = 20 }
};
private static IObservable<SensorReading> SimulateLiveData()
{
return ToObservableInterval(HistoricData, TimeSpan.FromMilliseconds(1000));
}
private static IObservable<T> ToObservableInterval<T>(IEnumerable<T> source, TimeSpan period)
{
return Observable.Using(
source.GetEnumerator,
it => Observable.Generate(
default(object),
_ => it.MoveNext(),
_ => _,
_ =>
{
//Console.WriteLine("Input {0}", it.Current);
return it.Current;
},
_ => period));
}
}