问题
If I have a list of objects that contains a timestamp - how can I make an observable that fire events at the relative time between the timestamps?
Eg. if I have three objects with timestamps 2014-01-01 10:30, 2014-01-01 10:45 and 2014-01-01 11:30, I want the first event to fire right away, then the next 15 minutes later, and the last one 45 minutes after that.
How can I speed up the process, so that 1 minute equals 1 second? So the first event would fire right away as before, but the next would come 15 seconds later instead of 15 minutes and so on.
回答1:
Lots of ways to do this I'm sure, but here's a quick sample using Observable.Generate to schedule events at a particular time. It uses a list of events - but given it works with an iterator, you can easily adapt it to use another source:
void Main()
{
var now = DateTime.Now;
var events = new List<Tuple<DateTime, string>> {
Tuple.Create(now.AddSeconds(5), "A"),
Tuple.Create(now.AddSeconds(10), "B"),
Tuple.Create(now.AddSeconds(15), "C")
};
var eventSource = Observable.Generate(
(IEnumerator<Tuple<DateTime,string>>)events.GetEnumerator(),
s => s.MoveNext(),
s => s,
s => s.Current.Item2, // the data
s => s.Current.Item1); // the timing
eventSource.Subscribe(Console.WriteLine);
}
This writes out "A", "B" and "C" and 5, 10 and 15 seconds after start-up.
To speed up time, you can put some logic around how the scheduled time is interpreted. Another way it to use the HistoricalScheduler
. See this answer for some insight on that.
回答2:
Easiest way is to merge an enumerable of observables like so
IEnumerable<Tuple<DateTimeOffset,string>> timeStamps = ...;
IObservable<Tuple<DateTimeOffset,string>> eventStamps = timeStamps
.Select(s => Observable.Timer(s.Item1).Select(e=>s))
.Merge();
As per James World's answer, to speed or slow time, you can add the historical scheduler as a second argument to Timer. (Give him the points for that bit. I didn't know about that before I read his answer )
Observable.Timer(s.Item1, historicalScheduler)
If you are wondering why DateTimeOffset rather than DateTime look at DateTime vs DateTimeOffset
The nice thing is that the code above works if timeStamps is either IEnumerable
or IObservable
. There is an overload of merge that works for either.
来源:https://stackoverflow.com/questions/22255205/observable-from-list-of-timetamps