Skip to content

Timer

1. 概要

Timer は、指定した時間が経過した後に Unit を発行するファクトリメソッドです。period を併せて指定すると、初回発行後も一定間隔で繰り返し発行し続けます。

遅延の起点は TimeSpan(相対時間)と DateTimeOffset(絶対時刻)の両方に対応しています。

2. シグネチャ

単発(TimeSpan)

csharp
public static Observable<Unit> Timer(TimeSpan dueTime, CancellationToken cancellationToken = default)

指定した TimeSpan が経過した後に Unit を 1 つ発行し、完了します。

csharp
Observable.Timer(TimeSpan.FromSeconds(3))

単発(DateTimeOffset)

csharp
public static Observable<Unit> Timer(DateTimeOffset dueTime, CancellationToken cancellationToken = default)

指定した絶対時刻に到達した時点で Unit を 1 つ発行し、完了します。

csharp
Observable.Timer(DateTimeOffset.UtcNow.AddMinutes(5))

繰り返し(TimeSpan + period)

csharp
public static Observable<Unit> Timer(TimeSpan dueTime, TimeSpan period, CancellationToken cancellationToken = default)

dueTime 経過後に最初の値を発行し、以降は period 間隔で繰り返し発行します。自動的には完了しません。

csharp
Observable.Timer(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2))

繰り返し(DateTimeOffset + period)

csharp
public static Observable<Unit> Timer(DateTimeOffset dueTime, TimeSpan period, CancellationToken cancellationToken = default)

指定した絶対時刻に最初の値を発行し、以降は period 間隔で繰り返し発行します。

csharp
Observable.Timer(DateTimeOffset.UtcNow.AddSeconds(10), TimeSpan.FromSeconds(5))

TimeProvider 指定バリエーション

csharp
public static Observable<Unit> Timer(TimeSpan dueTime, TimeProvider timeProvider, CancellationToken cancellationToken = default)
public static Observable<Unit> Timer(DateTimeOffset dueTime, TimeProvider timeProvider, 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)

上記すべてのオーバーロードに対応する TimeProvider 指定版です。テスト時にフェイクタイマーを注入したり、独自のスケジューリングを行う場合に使用します。

オーバーロードの使い分け

overload使う場面
Timer(TimeSpan)相対的な遅延後に 1 回だけ発行する
Timer(DateTimeOffset)特定の時刻に 1 回だけ発行する
Timer(TimeSpan, TimeSpan)初回遅延+周期的な繰り返し
Timer(DateTimeOffset, TimeSpan)特定時刻から周期的な繰り返し
TimeProvider 付きテスト容易性の確保、カスタムスケジューラの利用

3. マーブルダイアグラム

Timer のマーブルダイアグラム

単発の場合、dueTime が経過した時点で Unit を 1 つ発行し完了します。period 付きの場合、dueTime 後に最初の値を発行し、以降 period ごとに繰り返し発行し続けます。

4. サンプルコード

csharp
using R3;

// 3 秒後に 1 回だけ発行
Observable.Timer(TimeSpan.FromSeconds(3))
    .Subscribe(
        _ => Console.WriteLine("発火"),
        _ => Console.WriteLine("完了"));
// 出力(3 秒後): 発火
// 出力: 完了

// 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}"));
// 出力例:
// tick: 12:00:01
// tick: 12:00:03
// tick: 12:00:05
// ...(cts.Cancel() で停止)

// DateTimeOffset で特定時刻に発行
Observable.Timer(DateTimeOffset.UtcNow.AddMinutes(1))
    .Subscribe(_ => Console.WriteLine("1 分後に発火"));

// TimeProvider を指定(テスト向け)
var fakeTime = new FakeTimeProvider();
Observable.Timer(TimeSpan.FromSeconds(5), fakeTime)
    .Subscribe(_ => Console.WriteLine("5 秒後"));
fakeTime.Advance(TimeSpan.FromSeconds(5));
// 出力: 5 秒後

5. 補足

Interval との違い

Intervalperiod のみを受け取り、初回の発行も period 後に行われます。Interval(period)Timer(period, period) と等価です。初回遅延と周期を個別に設定したい場合は Timer を使用してください。

TimerFrame との違い

実時間ではなくフレーム数で遅延や繰り返しを指定したい場合は TimerFrame を使用してください。