はかせのラボ

私の頭の中を書いていく雑記ブログです

C# Unityでもコンソールアプリでもタイマイベントを簡単に作れるSystem.Timers.Timerの紹介

あいさつ

新年あけましておめでとうございます。
はかせです。

今回はC#が使える環境ならばほぼ全てでタイマイベントをサクッと作れる
System.Timers.Timerの紹介です。

使い方

using System.Timers;

private Timer timer;

//タイマーの設定
timer = new Timer(1000.0);
timer.Elapsed += TimerElapsed;

//タイマー開始
timer.Enabled = true;

//タイマイベントの処理
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
}

Timerクラスのインスタンスを作ってそのインスタンスのプロパティを
設定していくだけで簡単にタイマイベントができます。

Intervalがタイマイベントの間隔を設定するプロパティです。
値はミリ秒単位で設定します。

Elapsedは設定した時間が経過したとき呼ばれるイベントです。
ここにメソッドを追加することでタイマイベントができます。

Enabledはタイマーを動かすかどうかを設定します。
Enabledがtrueになった時から時間計測が始まります。
逆にタイマーを止めたいときはこの値をfalseにすればいいです。

TimerクラスはIDisposableを実装しているので、
使わなくなったらDisposeをお忘れなく。

注意

Timerクラスを用いて処理を呼び出したとき
その処理はワーカースレッドで処理されます。
つまりUnityAPIをTimerクラスのイベントで呼び出すことはできません
(ISynchronizeInvokeオブジェクトをメインスレッドで作成しアタッチすれば使えそうな雰囲気ですが、ISynchronizeInvokeはSystem.ComponentModel下のものなのでUnityと相性がいいとは思えないです)

当然解決策もあります。
一番メジャーだと思われるのはSynchronizationContextを使ったやり方ですね。
下記の記事でやっています。
hakase0274.hatenablog.com

ただUnityAPIを使う用事があるのならばTimerクラスではなく、
コルーチンを使うべきだと思います。

どういう時に使うか

私はUnityで使うならデバッグ用として割り切って使うのがいいと思います。

見てもらったようにほぼプロパティ設定だけで動きますし、
ON/OFFを動的に切り替えたり、処理を付け足したり外したりもできます。

なので一定間隔でインスペクタだと見づらい情報をテキストに書きだしたり、
指定時間内に何がどれだけ呼ばれたかとかをログとして出したりと言った使い方ですね。

もちろんコルーチンやasync/awaitでも実現できますが、記述量が違います。
何より脳死でも組めるのが良きです。

こういったデバッグ用の機能って色々欲しくなるんですけど、
本番では外すので膨大な記述や依存があると外すときめんどくさいです。
かといってライブラリ依存無しとかでやろうとすると
開発速度が遅れたり、変なバグの温床になったりします。

TimerはSystem下にあるので依存は増えないですし、
記述量も少ないので実装楽ちんです。

あとがき

今回はSystem.Timers.Timerのご紹介でした。
元々コンソールアプリやWindowアプリ作る時に使ってたんですが、
Unityでも使えるんじゃねと思い使ってみたら行けたので紹介してみました。

個人的にこういう脳死で使えるクラスは大好きなので、
よく使いますし、よく作ります。
(できているとは言っていない)

変なことやろうとすると「なんでそんなことするの?余計なお世話だよ!」ってなるんですが、
それ以外だと「そんなことまでやってくれるの?神!」ってなります。
手がねじ切れるほどの手のひらクルーですねw

何かこんな感じで楽に使えてちょっと便利みたいなクラスや機能があったら
是非教えてください。

それでは今回はこの辺でノシ