Timerコントロールを複数使う場合の注意点などを例を挙げて説明します。
尚、単体でのTimerコントロールの使い方については以下のページを参照下さい。
⇒Timerコントロールの使い方
複数のTimerコントロールをフォームに張り付けた場合には、 タイマイベントの発生が同じ時間間隔を設定しておいても同時には発生しません。 同時に起こった場合には最初に発生したイベントの処理が終わった後でしか 次のイベントが発生しない様です。 フォーム上に貼られた複数のTimerコントロールは同一のスレッド内で 動作しているためだと思います。
実際のプログラムでそのことを見ていきます。
先ず、フォーム上にTimerコントロールを2個貼り、Timer1、Timer2とします。 さらに表示用にTextBoxコントロールを貼り、MultiLineをTrueとし、ScrollbarをVerticalに設定します。 また、タイマーの開始・終了を行うButtonコントロールを貼ります。
フォームロードイベントではTimerの間隔を100msec(0.1sec)に設定し、 「開始」「停止」ボタンクリックイベントでTimerを開始及び停止しています。
注目点は、タイマ1のTickイベントで、テキストボックスに現在時刻表示を行いますが、 その後にSleepによる待ち処理を行っています。 このSleepは待ち時間が終わるまでは戻ってこないので、Tickイベントが待たされることになります。
複数のTimerコントロールの使い方
Public Class frmTimerMul '''''' フォームロードイベント ''' Private Sub frmTimer_Load(sender As Object, e As EventArgs) Handles Me.Load 'ラベルに現在時刻表示 Me.TextBox1.Text = "" 'Timerの間隔を100msec(0.1sec)に設定 Me.Timer1.Interval = 100 Me.Timer2.Interval = 100 'Timerを停止状態にする Me.Timer1.Enabled = False Me.Timer2.Enabled = False End Sub '''''' タイマ1Tickイベント ''' Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick 'テキストボックスに現在時刻表示 Me.TextBox1.Text &= "Timer1 = " & Now.ToString("hh:mm:ss.fff") & vbCrLf Me.TextBox1.Refresh() '5秒待たせる System.Threading.Thread.Sleep(5 * 1000) End Sub '''''' タイマ2Tickイベント ''' Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick 'テキストボックスに現在時刻表示 Me.TextBox1.Text &= "Timer2 = " & Now.ToString("hh:mm:ss.fff") & vbCrLf End Sub '''''' 「停止」ボタンクリックイベント ''' Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click 'Timerを停止する Me.Timer1.Stop() Me.Timer2.Stop() End Sub '''''' 「開始」ボタンクリックイベント ''' Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click 'TextBoxクリア Me.TextBox1.Text = "" 'Timerを開始する Me.Timer1.Start() Me.Timer2.Start() End Sub End Class
このプログラムを実行すると以下の様な表示になります。
Timer1の時刻表示が行われ、5秒後にTimer2の時刻表示が行われます。 Timer1、Timer2ともに0.1秒毎のタイマイベントが発生するのですが Timer1のタイマイベントではSleepによる5秒の待ちが在るため、 Timer2のタイマイベントが待たされている様です。 尚、Timer2のタイマイベント処理はすぐに終わるため、 Timer2の時刻と次のTimer1の時刻はほぼ同じものとなります。
そこで以下の様にして考察してみます。 Timer1、Timer2ともに5秒毎のインターバルとし、 Timer1のタイマイベント処理にMsgBoxの待ちを入れてみます。
Timerコントロールでの注意すること
Public Class frmTimerMul2 '''''' フォームロードイベント ''' Private Sub frmTimer_Load(sender As Object, e As EventArgs) Handles Me.Load 'ラベルに現在時刻表示 Me.TextBox1.Text = "" 'Timerの間隔を5000msec(5sec)に設定 Me.Timer1.Interval = 5000 Me.Timer2.Interval = 5000 'Timerを停止状態にする Me.Timer1.Enabled = False Me.Timer2.Enabled = False End Sub '''''' タイマ1Tickイベント ''' Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick 'テキストボックスに現在時刻表示 Dim strTime As String = "Timer1 = " & Now.ToString("hh:mm:ss.fff") & vbCrLf Me.TextBox1.Text &= strTime '待たせる MsgBox("Waiting..." & strTime, MsgBoxStyle.OkOnly, "タイマ1Tickイベント") End Sub '''''' タイマ2Tickイベント ''' Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick 'テキストボックスに現在時刻表示 Me.TextBox1.Text &= "Timer2 = " & Now.ToString("hh:mm:ss.fff") & vbCrLf End Sub '''''' 「停止」ボタンクリックイベント ''' Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click 'Timerを停止する Me.Timer1.Stop() Me.Timer2.Stop() End Sub '''''' 「開始」ボタンクリックイベント ''' Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click 'TextBoxクリア Me.TextBox1.Text = "" 'Timerを開始する Me.Timer1.Start() Me.Timer2.Start() End Sub End Class
これを実行して10数秒そのままにしておくと、以下の様なことが起こります。
Timer1のタイマイベントの中にMsgBoxを入れたことによりこの様になりました。
MsgBoxはボタンを持った1個のウインドウの様なもので、 この処理の中でウインドウのメッセージ処理が行われているため Timer1の次のタイマイベントの処理が受け付けられてしまい、次々とMsgBoxの表示がされてしまいます。 (ウインドウのメッセージ処理については、ここでは説明しませんがMsgBoxが行われることで 他のイベント処理を受付可能になるということです)
結果、タイマイベント処理の中ではあまり時間のかかる処理や、別のイベントを誘発するような処理は行わない方が良い様です。 (このことは、複数のTimerだからということではありませんが)
タイマコントロールではなく、スレッドを使ったタイマ処理は以下を参照して下さい。
関連する記事
⇒Timerコントロールの使い方 :[Timer,Interval]
⇒スレッドタイマの使い方 :[System.Threading.Timer,Delegate,Invoke]
⇒スレッドタイマの使い方(イベント処理が時間が掛かる場合):[System.Threading.Timer,Delegate,Invoke]
⇒引数があるスレッドの実行について(パラメータ付きスレッド)
⇒スレッドを停止させる方法について
コメント