.NET の Timer を考えよう(1)


何気なく使ってきた Timer について調べたい

.NET でアプリケーションなどを作っているときに、あまり気にしないでタイマー使ってますよね?私もそうでした。0.1秒程度のタイマー(Timer.Interval=100)あたりならさほど気にならないし、ずれても気にしない程度に使うわけです。たとえば、時刻を秒単位で表示するなんてのは、1秒に10回もやっとけば十分でしょう?でも、時間に厳しい(タイムクリティカルな)処理をやろうとすると、タイマーの性能というのが効いてきます。たぶんそうです。いや、きっとそう!……… と自信がないわけです。

FormでTimerを何気なく使うの図

で当然ググります。そうすると、こんな記事が出てくる。

ね、出てきたでしょ?出てこない?「dotnet timer」で検索したんですよ。僕は出てきたので、出てきた体(てい)でお願いしますよ。

Timer といってもいろいろある

この2つの記事で、次のようなことが分かります。

  1. System.Windows.Forms.Timer、System.Timers.Timer、System.Threading.Timer、DispatcherTimer (WPF) がある。
  2. それぞれの特徴はこんな感じ
    1. System.Windows.Forms.Timer
      • みんなが意識しないで使ってる普通のタイマー
      • UIスレッドでWindowメッセージ WM_TIMER で処理されるので遅い
      • UIスレッド※1で他の処理をしている間は動かないから、スレッドセーフ(Thread Safe)である
    2. System.Timers.Timer
      • マルチスレッドで走るようになっている。
      • System.Windows.Forms.Timer よりは正確らしい
      • UIスレッドでも走る
      • WPFではサポートされない→マイクロソフトはやめたい?
    3. System.Threading.Timer
      • タイマーの終了は新しく生成したスレッドのイベントで受け取る
      • 名前とは違って、スレッドセーフではないのでUIがらみでは使わないほうがいい
      • クラスの継承はできない
    4. DispatcherTimer (WPF)
      • WPF※2ベースで、Abhishek Sur さんご愛用
      • スレッドセーフである
      • UIスレッド内で動くのが基本
      • System.Windows.Forms.Timer と同じに使える
      • WPFのアプリケーションでは最強と、Abhishek Sur さんご推薦
  3. 当面の結論は、.NET 3.5 以降なら DispatcherTimer がおススメ

System.Windows.Forms.Timer より正確なタイマーが欲しいときは、System.Timers.Timer を止めて DispatcherTimer に乗り換えましょうということらしいんですね。

Timer の「正確さ」を知りたい!

そもそも、タイマーの「正確さ」ってなんでしょう?次のようなことを考えましょう。

  1. あるタイミングで間違いなく時間内に処理が終了する(ストップウォッチ的)
  2. 長いスパンで見たときに、平均したタイマー間隔が間違いなくインターバル時間である(時計の正確さ的)

どうもよく考えると両立するのは難しいように思えます。しかもそのうえで、

  1. 面倒がなくて使いやすい

ということも大事です。System.Threading.Timer は意外に面倒だったりするらしい。そんなわけで、Abhishek Sur さんの TimersDemo を試しながら、そのあたりを考えてみましょう。

VS2010でソリューションファイルを開く

TimersDemo.sln をダブルクリックして、Visual Studio 2010 で開きます。いきなりビルドして実行するとこんな画面。うーーん、動くことはわかるけど、これじゃぁ分かりません。ソースを眺めるもんなんですね。C# で書かれたソース見ながらもう少し考えましょうか。でも、今日はここまで。続きをまた書きます。

TimersDemo実行

clock.NET の Timer を考えよう 1|

 

※1 UIスレッド:ざっくり言えば、フォーム内のユーザインタフェース(UI)処理にかかわる関数がひとまとまりに動く単位=スレッドです。スレッド内部では、イベントハンドラを除く複数の関数が同時に処理されることはありません。たとえば、ある関数で配列に要素を加えている途中で、別の関数が割り込んできて配列から要素を削除したりすると、オブジェクトが壊れてしまうということが起きます。スレッドセーフ(Thread Safe)というのはそういうことが起きても困らないようになってるよということです。今回の例でいえば、タイマーオブジェクトが属するスレッドと、タイマーイベントハンドラが属するスレッドが異なるときにスレッドセーフかどうかが問題となります。

※2 WPF:Windows Presentation Foundationのこと。.NET Framework 3.0以降に含まれるユーザインタフェースのフレームワークである(http://www.wpftutorial.net/WPFIntroduction.html より)

印刷
You can skip to the end and leave a response. Pinging is currently not allowed.
Subscribe to RSS Feed Twitter は Ume108 だよ