.NET Frameworkには、タイマと呼ばれるものが3つあります。
- System.Timers.Timer
- System.Threading.Timer
- System.Windows.Forms.Timer
一つ目が、今回対象となるTimerクラスです。このクラスは、コンポーネントとなっています。
一般的に、サーバータイマ(サーバーベースのタイマとも言います)と呼ばれます。
マルチスレッド環境で、ワーカースレッドとともに利用するのが主です。
二つ目は、スレッドタイマと呼ばれるTimerクラスです。
このTimerクラスは、プログラム内部でのみ利用できます。(他のタイマはツールボックスから利用できます。)
最も軽量なタイマで、イベントの代わりにコールバックを利用します。
三つ目は、Windowsタイマと呼ばれます。
UIを持つアプリケーションから利用出来るよう最適化されています。
具体的には、常にイベントがUIスレッドから呼ばれます。
System.Timers.TimerとSystem.Threading.Timerは、ThreadPoolを利用します。
対して、System.Windows.Forms.TimerはUIスレッド固定です。
どのTimerも使い方は、ほとんど変わりません。
利用する箇所で使い分けるのが、一般的です。
で、今回のSystem.Timers.Timerですが、このタイマは上述したように
マルチスレッド処理の中で利用したり、サーバー側の処理にて利用したりするのが一般的です。
また、Windowsアプリケーションでの利用も想定されていますので、使い勝手がいいのです。
以下、サンプルです。
#region System.Timers.Timerのサンプル public class ServerTimerSamples01 : Form, IExecutable { System.Timers.Timer _timer; ListBox _listBox; public ServerTimerSamples01() { InitializeComponent(); SetTimer(); } void InitializeComponent() { SuspendLayout(); Text = "Timer Sample."; FormClosing += OnFormClosing; _listBox = new ListBox(); _listBox.Dock = DockStyle.Fill; Controls.Add(_listBox); ResumeLayout(); } void SetTimer() { _timer = new System.Timers.Timer(); // // イベントをハンドル. // _timer.Elapsed += OnTimerElapsed; // // System.Timers.Timerはサーバータイマの為 // ThreadPoolにてイベントが発生する。 // // Elapsedイベント内で、UIコントロールにアクセスする必要がある場合 // そのままだと、別スレッドからコントロールに対してアクセスしてしまう可能性があるので // イベント内にて、Control.Invokeするか、以下のようにSynchronizingObjectを // 設定して、イベントの呼び出しをマーシャリングするようにする。 // // 純粋にサーバー側でタイマとして利用する場合は何も設定する必要はない. // _timer.SynchronizingObject = this; // // 繰り返しの設定. // _timer.Interval = 1000; _timer.AutoReset = true; // // タイマを開始. // _timer.Enabled = true; } public void Execute() { Application.EnableVisualStyles(); Application.Run(new ServerTimerSamples01()); } void OnFormClosing(object sender, FormClosingEventArgs e) { _timer.Enabled = false; _timer.Dispose(); } void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) { _listBox.Items.Add(String.Format("Time:{0}, ThreadID:{1}", e.SignalTime.ToString("HH:mm:ss"), Thread.CurrentThread.ManagedThreadId.ToString())); } } #endregion
上記ソースの、
_timer.SynchronizingObject = this;
の部分をコメントアウトにして、実行すると
今度は、各時刻がリストボックスに表示される際にThreadIDが異なってきます。
(ちなみに、本来このような場合はControl.Invokeするのが定石ですが、サンプルなので割愛してます。)
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場