一分ごとにタイマーイベントを発生させたいと考えています。
timer1.Interval = 60000
Private Sub timer1_Timer()
処理1
labe1.caption=now()
処理2
end sub
において何度かイベントが起こっていると時間がずれてきます。
イベント内でTimer1.Enable=Falseはしていません。
タイマーイベント内の処理が終了するまで次のインターバルは開始されないのでしょうか?
Timer の精度が悪いのは有名な話です。
キーワード『Timer 正確 VB』などでぐーぐる検索してみてください。
Timerのズレに関しては、すでに書かれてるので置いといて、
余談になりますが、Timerイベントの処理が終了しなくてもTimerは止めない限り
OS任せで(?)動きっぱなしで、次のイベントは時間が来れば発生するはずです
とは言え、Timerイベントプロシージャ内でDoEvents書いたりしてOSに処理が
戻らない限り、実際に処理は走らない(待ち状態になる)ような気もしますが…
時間計測などを行う処理でなく、Timerイベントプロシージャの処理が
時間が掛かるものであれば、処理の最初でTimerを止め、処理終了時に
Timerを再起動するのが良いかもしれません
(あくまで余談ですので、訳わかんなければ放置してください)
特攻隊長まるるうさん、あさん ありがとうございます。
おっしゃるとおり調べてみましたらTimerの誤差の原因あるみたいですね。
しかしながら、その誤差より更に大きい気がして
timerイベント内でsleep(10000)をしてみました。
すると次のtimerイベントまでに70秒と10秒遅れます。
やはりtimerイベント終了後から60秒とっているような・・・。
チェックボックスとテキストボックス「0をいれておく」でどうでしょう?
マルチ処理は出来なく、プロセジャ実行中にプロセジャ実行はできないかと。。。解決?
Private Sub Timer1_Timer()
Form1.Text1.Text = CStr(CLng(Form1.Text1.Text) + 1)
Do
DoEvents
If Check1.Value = 1 Then
Exit Do
End If
Loop
End Sub
ふむ…そうなるなら、「Timerイベントプロシージャ処理中はTimerが待つ」または
「Timerの管理はあくまでアプリ内で行う(OS任せではない)仕様で、Sleep APIは
スレッドを完全に停止させるから+10秒掛かった」かの、どちらかかもしれない
私の認識が足りなかったようで…失礼
ただ、これだけでは、Timerが待ってくれるのかどうかは確定ではない気がする
…知ってる方、補足願いたい
(Sleepでスレッドが完全に停止するのは確実)
ちなみに通りすがり氏の内容は、「処理中フラグ」を作って制御している…
みたいな方法、なのだろうか?
確かに、その手のフラグで逃げたことはあるが(Timerでは無かった気が…)
Interval プロパティーが 60000 に設定された Timer1 の Timer1_Timerイベントは、
60秒に置きに発生するのではなく、前回の Timer1_Timerイベント が終了してから 60秒経ったら発生します。
よって、Timer1_Timerイベントが発生してイベントが終わるまでに20秒かかる場合は、80秒置きに発生するということになります。
また、Timer1_Timerイベントのコードの中に DoEvents を入れていたとしても、
Timer1_Timerイベント実行中にまた Timer1_Timerイベント が発生してしまうということもありません。
Timer1_Timerイベントが終わるまで待っています。
一分ごとにタイマーイベントを発生させたいときは、
Timer1_Timerイベントのコードの最初と最後に時刻を測定して Timer1_Timerイベント にかかった時間を計って、その時間を60秒から差し引いた値をInterval プロパティーにセットすればうまくと思います。
Timer1.Interval = 60000
Private Sub timer1_Timer()
Start = Timer
処理1
labe1.caption=now()
処理2
Finish = Timer
TotalTime = Finish - Start
Timer1.Interval = 60000 - TotalTime * 1000
end sub
補足)
上の方法でもほんの少しずつですが、ずれが出てきます。(ずれが蓄積していく)。
Timer関数(1秒単位)ではなく API の GetTickCount(1m秒単位) を使えばずれは少なくなります。
時報のように正確に(ずれが蓄積しないように)一分おきに発生させたいときは、経過時間ではなく時刻を取得してInterval プロパティーを調節してやる必要があります。
また、場合によっては、 Timer1_Timerイベントに60秒以上かかってしまったときの対策も必要となります。
下の例は、Timer1_Timerイベントに60秒以上かかった場合の対策をしていない場合のものです。
Dim mTime As Date 'Timerイベントの実行予定時刻が入るモジュール変数。
Private Sub Command1_Click()
'スタート
Timer1.Enabled = False
mTime = DateAdd("n", 1, Now) '予定時刻をセット。
Timer1.Interval = 60000
Timer1.Enabled = True
End Sub
Private Sub timer1_Timer()
処理1
labe1.Caption = Now()
処理2
mTime = DateAdd("n", 1, mTime) '一分後に予定。
Timer1.Interval = DateDiff("s", Now, mTime) * 1000 '予定とのずれを調節する。
End Sub
現状ではタイマーイベント内の処理で60秒以上かかることがないので
Qさまのプログラムを参考にさせていただきなんとかタイマーの誤差を
補正することができました。
ご意見ご指導くだされた皆様本当にありがとうございました。