【VB.NET】System.Windows.Forms.Timerを長時間動作させると実行時刻が徐々にずれる
実現したいこと
- 常駐アプリで、毎分ほぼ00秒に処理を実行したい
- 長時間動作させても、実行開始時刻が徐々に遅れないようにしたい
前提
VB.NETの.NET Framework 4.8でWindows Formsアプリケーションを作成しています。
このアプリは常駐アプリとしてWindows 11上で長時間動作させています。
毎分1回DBへの登録処理を行っており、処理開始時刻を毎分ほぼ00秒に合わせるため
TimerのTick処理内で以下のような処理を行っています。
TimerをStop()する
DB登録処理を実行する
DateTime.Nowから次の00秒までの待機時間を計算する
Timerを再生成する
計算した待機時間をIntervalに設定してStart()する
この方法であれば、DB登録処理にかかった時間が次回以降に累積することはないと考えていました。
実際、アプリ起動直後はほぼ00秒に処理が開始されています。
しかし、長時間動作させると正分からの遅延が徐々に大きくなります。
※Windows 10で同じアプリを動作させていた際には、このような現象は発生していませんでした。
発生している問題・エラーメッセージ
エラーメッセージはありません。
処理開始時刻が時間の経過とともに徐々に遅れて行きます。
アプリ起動直後:
2026/09/09 00:00:00 履歴テーブル書き込み開始 : 2026/09/09 00:00:00
2026/09/09 00:00:00 DB登録待ち待機開始 : 2026/09/09 00:00:00
2026/09/09 00:00:06 DB登録待ち待機終了 : 2026/09/09 00:00:06
2026/09/09 00:00:08 書き込みOK : 2026/09/09 00:00:08
2026/09/09 00:00:08 起動時間の調整 [ 51.98 ]秒 待機
2026/09/09 00:01:00 履歴テーブル書き込み開始 : 2026/09/09 00:01:00
2026/09/09 00:01:00 DB登録待ち待機開始 : 2026/09/09 00:01:00
2026/09/09 00:01:06 DB登録待ち待機終了 : 2026/09/09 00:01:06
2026/09/09 00:01:08 書き込みOK : 2026/09/09 00:01:08
2026/09/09 00:01:09 起動時間の調整 [ 50.949 ]秒 待機
長時間動作時(1行目、6行目の開始時間が02になっています。):
2026/09/15 00:00:02 履歴テーブル書き込み開始 : 2026/09/15 00:00:02
2026/09/15 00:00:04 DB登録待ち待機開始 : 2026/09/15 00:00:04
2026/09/15 00:00:12 DB登録待ち待機終了 : 2026/09/15 00:00:12
2026/09/15 00:00:17 書き込みOK : 2026/09/15 00:00:17
2026/09/15 00:00:19 起動時間の調整 [ 40.110 ]秒 待機
2026/09/15 00:01:02 履歴テーブル書き込み開始 : 2026/09/15 00:01:02
2026/09/15 00:01:05 DB登録待ち待機開始 : 2026/09/15 00:01:05
2026/09/15 00:01:13 DB登録待ち待機終了 : 2026/09/15 00:01:13
2026/09/15 00:01:17 書き込みOK : 2026/09/15 00:01:17
2026/09/15 00:01:19 起動時間の調整 [ 40.380 ]秒 待機
該当のソースコード
Private Sub oTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles oTimer.Tick
Dim bRet As Boolean
'' タイマー停止
oTimer.Stop()
Try
'' ログ名設定
If Mid(m_LogName, 9, 8) <> Format(Now, "yyyyMMdd") Then
m_LogName = "OPE_PRO_" & Format(Now, "yyyyMMdd") & ".log"
End If
'' 履歴テーブルへ書き込み
'PrvS_AddHist("_/_/_/_/_/_/_/_/_/_/書き込み開始_/_/_/_/_/_/_/_/_/_/")
PrvS_AddHist("履歴テーブル書き込み開始 : " & CStr(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")))
bRet = PrvF_WriteOpeHist()
If bRet = False Then
PrvS_AddHist("書き込みNG : " & CStr(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")))
Return
End If
PrvS_AddHist("書き込みOK : " & CStr(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")))
Catch ex As Exception
PrvS_AddHist("システムエラー" & ex.Message)
End Try
'' 正分に動作するように待つ
Dim dt As DateTime = DateTime.Now
Dim nSec As Integer = CInt(dt.Second)
Dim nMilSec As Integer = CInt(dt.Millisecond)
Dim nInterval As Integer = (1000 * (59 - nSec)) + (1000 - nMilSec)
'' タイマオブジェクトを生成する
oTimer = New Timer()
oTimer.Interval = (nInterval)
PrvS_AddHist("起動時間の調整 [ " & nInterval & " ]ms 待機")
oTimer.Start()
End Sub
試したこと
-
別の機器にて同様の環境を用意し実施
→同様の現象を確認しました。
補足情報(FW/ツールのバージョンなど)
System.Windows.Forms.Timerの仕様、UIスレッドの処理、Windows 10とWindows 11の違いなど
どのような原因が考えられるかを知りたいです。
OS:Windows 11
開発環境:Visual Studio 2022
言語:VB.NET
.NET Framework:4.8
アプリケーション:Windows フォーム アプリケーション
常駐アプリとして長時間動作
Timer:System.Windows.Forms.Timer
DBへの登録処理あり
※同じアプリをWindows 10で動作させていた際には今回のような現象は発生していませんでした。