Chỉ cần sử dụng quá tải Timer chấp nhận giá trị DateTimeOffset
. Bạn có thể sử dụng Defer
và Repeat
để tạo "khoảng thời gian tuyệt đối".
Observable.Defer(() =>
DateTime.Now.Hour < 9
? Observable.Timer(DateTime.Today.AddHours(9))
: DateTime.Now.Hour < 13
? Observable.Timer(DateTime.Today.AddHours(13))
: Observable.Timer(DateTime.Today.AddDays(1).AddHours(9)))
.Repeat()
.Subscribe(...);
Rx automatically ensures, đến hết khả năng của mình, mà thông báo của bạn sẽ xảy ra vào ngày chính xác và thời gian nhất định, ngay cả với đối với timer trôi dạt và nếu những thay đổi hệ thống đồng hồ trước thời gian hẹn giờ đã trôi qua.
Dưới đây là một phương pháp tiện ích mở rộng tổng quát vấn đề hơn nữa.
Cách sử dụng:
Observable2.Daily(TimeSpan.FromHours(9), TimeSpan.FromHours(13)).Subscribe(...);
Định nghĩa:
public static partial class Observable2
{
public static IObservable<long> Daily(params TimeSpan[] times)
{
Contract.Requires(times != null);
Contract.Requires(Contract.ForAll(times, time => time > TimeSpan.Zero));
Contract.Requires(Contract.ForAll(times, time => time.TotalDays < 1));
return Daily(Scheduler.Default, times);
}
public static IObservable<long> Daily(IScheduler scheduler, params TimeSpan[] times)
{
Contract.Requires(times != null);
Contract.Requires(Contract.ForAll(times, time => time > TimeSpan.Zero));
Contract.Requires(Contract.ForAll(times, time => time.TotalDays < 1));
if (times.Length == 0)
return Observable.Never<long>();
// Do not sort in place.
var sortedTimes = times.ToList();
sortedTimes.Sort();
return Observable.Defer(() =>
{
var now = DateTime.Now;
var next = sortedTimes.FirstOrDefault(time => now.TimeOfDay < time);
var date = next > TimeSpan.Zero
? now.Date.Add(next)
: now.Date.AddDays(1).Add(sortedTimes[0]);
Debug.WriteLine("Next @" + date + " from " + sortedTimes.Aggregate("", (s, t) => s + t + ", "));
return Observable.Timer(date, scheduler);
})
.Repeat()
.Scan(-1L, (n, _) => n + 1);
}
}
Cập nhật:
Nếu bạn muốn có nhiều "chức năng" trong cách tiếp cận của bạn bằng cách xác định đầu vào như một chuỗi vô hạn từ một trình lặp chặn, theo câu trả lời của Jeroen Mostert, thì bạn có thể sử dụng Generate
như sau.
Observable.Generate(
GetScheduleTimes().GetEnumerator(),
e => e.MoveNext(),
e => e,
e => e.Current,
e => e.Current);
câu trả lời Jeroen Mostert của (xóa) cung cấp một thực hiện ví dụ về GetScheduleTimes
, nhưng về cơ bản nó chỉ là một khối iterator mà mang lại một dãy vô hạn các DateTimeOffset
giá trị trong một vòng lặp while, với mỗi vòng lặp incrementing các giá trị ngày tới 1.
Bạn có thể tính toán thời gian cho đến lần kích hoạt tiếp theo và sử dụng bộ hẹn giờ với thời gian chờ đó (kiểm tra tham số 'dueTime' trong [Threading.Timer] (http://msdn.microsoft.com/en- us/library/3yb9at7c (v = vs.110) .aspx)) – Jcl
Viết mã của bạn theo cách mà bạn có thể sử dụng Windows Task Scheduler vì đây là những gì nó được thiết kế d cho. – JRLambert