Timer
1. 概要
Timer は、指定した時間または時刻に Unit を発行するファクトリメソッドです。
dueTime だけを指定する overload は、指定時間が経過した時点、または指定時刻に到達した時点で Unit を 1 つ発行し、その直後に完了します。period も指定する overload は、初回発行後も period 間隔で Unit を発行し続け、自動的には完了しません。
遅延の起点は TimeSpan による相対時間と、DateTimeOffset による絶対時刻の両方に対応しています。TimeProvider を指定する overload では、使用する時計やタイマーを差し替えられます。CancellationToken がキャンセルされると、購読中のタイマーは完了して停止します。
2. シグネチャ
指定時間後に 1 回だけ発行する
public static Observable<Unit> Timer(TimeSpan dueTime, CancellationToken cancellationToken = default)
public static Observable<Unit> Timer(DateTimeOffset dueTime, CancellationToken cancellationToken = default)
public static Observable<Unit> Timer(TimeSpan dueTime, TimeProvider timeProvider, CancellationToken cancellationToken = default)
public static Observable<Unit> Timer(DateTimeOffset dueTime, TimeProvider timeProvider, CancellationToken cancellationToken = default)dueTime に指定した相対時間が経過した後、または絶対時刻に到達した時点で Unit を 1 つ発行し、完了します。TimeProvider 指定版では、既定の ObservableSystem.DefaultTimeProvider ではなく、指定した TimeProvider の時刻とタイマーを使用します。
Observable.Timer(TimeSpan.FromSeconds(3))
Observable.Timer(DateTimeOffset.UtcNow.AddMinutes(5))
Observable.Timer(TimeSpan.FromSeconds(3), TimeProvider.System)この例では、dueTime が経過したタイミングで Unit を 1 つ発行し、直後に完了します。
初回遅延後に一定間隔で繰り返す
public static Observable<Unit> Timer(TimeSpan dueTime, TimeSpan period, CancellationToken cancellationToken = default)
public static Observable<Unit> Timer(DateTimeOffset dueTime, TimeSpan period, CancellationToken cancellationToken = default)
public static Observable<Unit> Timer(TimeSpan dueTime, TimeSpan period, TimeProvider timeProvider, CancellationToken cancellationToken = default)
public static Observable<Unit> Timer(DateTimeOffset dueTime, TimeSpan period, TimeProvider timeProvider, CancellationToken cancellationToken = default)dueTime で初回発行のタイミングを指定し、その後は period 間隔で Unit を発行し続けます。自動的には完了しないため、CancellationToken、購読解除、または Take などで停止条件を与えます。period に負の値を指定すると ArgumentOutOfRangeException が発生します。
Observable.Timer(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2))
Observable.Timer(DateTimeOffset.UtcNow.AddSeconds(10), TimeSpan.FromSeconds(5))
Observable.Timer(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeProvider.System)この例では、dueTime 経過後に最初の Unit を発行し、その後は period ごとに Unit を発行し続けます。
overload の使い分け
| overload | 使う場面 |
|---|---|
Timer(TimeSpan) | 相対的な遅延後に 1 回だけ発行する |
Timer(DateTimeOffset) | 特定の時刻に 1 回だけ発行する |
Timer(TimeSpan, TimeSpan) | 初回遅延と周期を分けて、一定間隔で繰り返す |
Timer(DateTimeOffset, TimeSpan) | 特定時刻から周期的な繰り返しを始める |
各 TimeProvider 付き | テスト容易性の確保、カスタムスケジューラの利用 |
3. サンプルコード
using R3;
// 3 秒後に 1 回だけ発行して完了
Observable.Timer(TimeSpan.FromSeconds(3))
.Subscribe(
_ => Console.WriteLine("発火"),
_ => Console.WriteLine("完了"));using R3;
// 1 秒後に初回発行、以降 2 秒ごとに繰り返し
var cts = new CancellationTokenSource();
Observable.Timer(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), cts.Token)
.Subscribe(_ => Console.WriteLine($"tick: {DateTime.Now:HH:mm:ss}"));
// cts.Cancel() で停止using R3;
// DateTimeOffset で特定時刻に発行
Observable.Timer(DateTimeOffset.UtcNow.AddMinutes(1))
.Subscribe(_ => Console.WriteLine("1 分後に発火"));using R3;
// TimeProvider を指定
Observable.Timer(TimeSpan.FromSeconds(5), TimeProvider.System)
.Subscribe(_ => Console.WriteLine("5 秒後"));4. 補足
Interval との違い
Interval は period のみを受け取り、初回の発行も period 後に行われます。Interval(period) は Timer(period, period) と同じ用途で使えます。初回遅延と周期を別々に指定したい場合は Timer を使用してください。
TimerFrame との違い
実時間ではなくフレーム数で遅延や繰り返しを指定したい場合は TimerFrame を使用してください。