Skip to content

Timer

1. 概要

Timer は、指定した時間または時刻に Unit を発行するファクトリメソッドです。

dueTime だけを指定する overload は、指定時間が経過した時点、または指定時刻に到達した時点で Unit を 1 つ発行し、その直後に完了します。period も指定する overload は、初回発行後も period 間隔で Unit を発行し続け、自動的には完了しません。

遅延の起点は TimeSpan による相対時間と、DateTimeOffset による絶対時刻の両方に対応しています。TimeProvider を指定する overload では、使用する時計やタイマーを差し替えられます。CancellationToken がキャンセルされると、購読中のタイマーは完了して停止します。

2. シグネチャ

指定時間後に 1 回だけ発行する

csharp
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 の時刻とタイマーを使用します。

csharp
Observable.Timer(TimeSpan.FromSeconds(3))
Observable.Timer(DateTimeOffset.UtcNow.AddMinutes(5))
Observable.Timer(TimeSpan.FromSeconds(3), TimeProvider.System)

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

この例では、dueTime が経過したタイミングで Unit を 1 つ発行し、直後に完了します。

初回遅延後に一定間隔で繰り返す

csharp
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 が発生します。

csharp
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)

Timer 繰り返しのマーブルダイアグラム

この例では、dueTime 経過後に最初の Unit を発行し、その後は period ごとに Unit を発行し続けます。

overload の使い分け

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

3. サンプルコード

csharp
using R3;

// 3 秒後に 1 回だけ発行して完了
Observable.Timer(TimeSpan.FromSeconds(3))
    .Subscribe(
        _ => Console.WriteLine("発火"),
        _ => Console.WriteLine("完了"));
csharp
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() で停止
csharp
using R3;

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

// TimeProvider を指定
Observable.Timer(TimeSpan.FromSeconds(5), TimeProvider.System)
    .Subscribe(_ => Console.WriteLine("5 秒後"));

4. 補足

Interval との違い

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

TimerFrame との違い

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