Timer의 오버로드를 사용하면 DateTimeOffset
값을 사용할 수 있습니다. Defer
및 Repeat
을 사용하여 "절대 간격"을 만들 수 있습니다. 알림도 타이머 드리프트과 관련하여 타이머 시간 전에 시스템 클럭 변경이 경과 한 경우, 지정된 정확한 날짜와 시간에 발생하는 것이 능력의 최선을
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(...);
수신 automatically ensures,.
다음은이 문제를 일반화하는 확장 방법입니다.
사용법 :
Observable2.Daily(TimeSpan.FromHours(9), TimeSpan.FromHours(13)).Subscribe(...);
정의 :
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);
}
}
업데이트 :
당신이 입력을 정의하여 접근 방식에 더 많은 "기능"싶은 경우 반복자에서 무한한 시퀀스로 블록, Jeroen Mostert의 답변에 따라 다음과 같이 Generate
을 사용할 수 있습니다.
Observable.Generate(
GetScheduleTimes().GetEnumerator(),
e => e.MoveNext(),
e => e,
e => e.Current,
e => e.Current);
제론 Mostert의 답변 (는 삭제) GetScheduleTimes
의 예시적인 구현을 제공하지만, 기본적으로이 값을 '증가 각각 루프, while 루프에 DateTimeOffset
값 무한 시퀀스를 수득 단지 반복기 블록이었다 일을 기준으로 계산합니다.
다음 트리거까지의 시간을 계산하고 해당 시간 초과가있는 타이머를 사용합니다 ([Threading.Timer]의 매개 변수 'dueTime'확인 (http://msdn.microsoft.com/en- us/library/3yb9at7c (v = vs.110) .aspx)) – Jcl
Windows 작업 스케줄러를 사용할 수있는 방식으로 코드를 작성하십시오. d를 위해. – JRLambert