VB.NET Tips - 複数のTimerコントロールの使い方

Timerコントロールを複数使う場合の注意点などを例を挙げて説明します。
尚、単体でのTimerコントロールの使い方については以下のページを参照下さい。

Timerコントロールの使い方

複数のTimerコントロールをフォームに張り付けた場合には、 タイマイベントの発生が同じ時間間隔を設定しておいても同時には発生しません。 同時に起こった場合には最初に発生したイベントの処理が終わった後でしか 次のイベントが発生しない様です。 フォーム上に貼られた複数のTimerコントロールは同一のスレッド内で 動作しているためだと思います。

実際のプログラムでそのことを見ていきます。
先ず、フォーム上にTimerコントロールを2個貼り、Timer1Timer2とします。 さらに表示用にTextBoxコントロールを貼り、MultiLineTrueとし、ScrollbarVerticalに設定します。 また、タイマーの開始・終了を行うButtonコントロールを貼ります。

フォームロードイベントではTimerの間隔を100msec(0.1sec)に設定し、 「開始」「停止」ボタンクリックイベントでTimerを開始及び停止しています。
注目点は、タイマ1のTickイベントで、テキストボックスに現在時刻表示を行いますが、 その後にSleepによる待ち処理を行っています。 このSleepは待ち時間が終わるまでは戻ってこないので、Tickイベントが待たされることになります。

複数のTimerコントロールの使い方

01Public Class frmTimerMul
02 
03    ''' <summary>
04    ''' フォームロードイベント
05    ''' </summary>
06    Private Sub frmTimer_Load(sender As Object, e As EventArgs) Handles Me.Load
07        'ラベルに現在時刻表示
08        Me.TextBox1.Text = ""
09        'Timerの間隔を100msec(0.1sec)に設定
10        Me.Timer1.Interval = 100
11        Me.Timer2.Interval = 100
12        'Timerを停止状態にする
13        Me.Timer1.Enabled = False
14        Me.Timer2.Enabled = False
15    End Sub
16 
17    ''' <summary>
18    ''' タイマ1Tickイベント
19    ''' </summary>
20    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
21        'テキストボックスに現在時刻表示
22        Me.TextBox1.Text &= "Timer1 = " & Now.ToString("hh:mm:ss.fff") & vbCrLf
23        Me.TextBox1.Refresh()
24        '5秒待たせる
25        System.Threading.Thread.Sleep(5 * 1000)
26    End Sub
27 
28    ''' <summary>
29    ''' タイマ2Tickイベント
30    ''' </summary>
31    Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
32        'テキストボックスに現在時刻表示
33        Me.TextBox1.Text &= "Timer2 = " & Now.ToString("hh:mm:ss.fff") & vbCrLf
34    End Sub
35 
36    ''' <summary>
37    ''' 「停止」ボタンクリックイベント
38    ''' </summary>
39    Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click
40        'Timerを停止する
41        Me.Timer1.Stop()
42        Me.Timer2.Stop()
43    End Sub
44 
45    ''' <summary>
46    ''' 「開始」ボタンクリックイベント
47    ''' </summary>
48    Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
49        'TextBoxクリア
50        Me.TextBox1.Text = ""
51        'Timerを開始する
52        Me.Timer1.Start()
53        Me.Timer2.Start()
54    End Sub
55 
56End Class

このプログラムを実行すると以下の様な表示になります。

Timer1の時刻表示が行われ、5秒後にTimer2の時刻表示が行われます。 Timer1、Timer2ともに0.1秒毎のタイマイベントが発生するのですが Timer1のタイマイベントではSleepによる5秒の待ちが在るため、 Timer2のタイマイベントが待たされている様です。 尚、Timer2のタイマイベント処理はすぐに終わるため、 Timer2の時刻と次のTimer1の時刻はほぼ同じものとなります。

そこで以下の様にして考察してみます。 Timer1、Timer2ともに5秒毎のインターバルとし、 Timer1のタイマイベント処理にMsgBoxの待ちを入れてみます。

Timerコントロールでの注意すること

01Public Class frmTimerMul2
02 
03    ''' <summary>
04    ''' フォームロードイベント
05    ''' </summary>
06    Private Sub frmTimer_Load(sender As Object, e As EventArgs) Handles Me.Load
07        'ラベルに現在時刻表示
08        Me.TextBox1.Text = ""
09        'Timerの間隔を5000msec(5sec)に設定
10        Me.Timer1.Interval = 5000
11        Me.Timer2.Interval = 5000
12        'Timerを停止状態にする
13        Me.Timer1.Enabled = False
14        Me.Timer2.Enabled = False
15    End Sub
16 
17    ''' <summary>
18    ''' タイマ1Tickイベント
19    ''' </summary>
20    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
21        'テキストボックスに現在時刻表示
22        Dim strTime As String = "Timer1 = " & Now.ToString("hh:mm:ss.fff") & vbCrLf
23        Me.TextBox1.Text &= strTime
24        '待たせる
25        MsgBox("Waiting..." & strTime, MsgBoxStyle.OkOnly, "タイマ1Tickイベント")
26    End Sub
27 
28    ''' <summary>
29    ''' タイマ2Tickイベント
30    ''' </summary>
31    Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
32        'テキストボックスに現在時刻表示
33        Me.TextBox1.Text &= "Timer2 = " & Now.ToString("hh:mm:ss.fff") & vbCrLf
34    End Sub
35 
36    ''' <summary>
37    ''' 「停止」ボタンクリックイベント
38    ''' </summary>
39    Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click
40        'Timerを停止する
41        Me.Timer1.Stop()
42        Me.Timer2.Stop()
43    End Sub
44 
45    ''' <summary>
46    ''' 「開始」ボタンクリックイベント
47    ''' </summary>
48    Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
49        'TextBoxクリア
50        Me.TextBox1.Text = ""
51        'Timerを開始する
52        Me.Timer1.Start()
53        Me.Timer2.Start()
54    End Sub
55 
56End Class

これを実行して10数秒そのままにしておくと、以下の様なことが起こります。

Timer1のタイマイベントの中にMsgBoxを入れたことによりこの様になりました。
MsgBoxはボタンを持った1個のウインドウの様なもので、 この処理の中でウインドウのメッセージ処理が行われているため Timer1の次のタイマイベントの処理が受け付けられてしまい、次々とMsgBoxの表示がされてしまいます。 (ウインドウのメッセージ処理については、ここでは説明しませんがMsgBoxが行われることで 他のイベント処理を受付可能になるということです)

結果、タイマイベント処理の中ではあまり時間のかかる処理や、別のイベントを誘発するような処理は行わない方が良い様です。 (このことは、複数のTimerだからということではありませんが)

総アクセス数