トップ回答者
タイマーを正確にミリ秒単位で動かしたい

質問
-
ストアアプリで指定されたミリ秒間隔でデータを取る処理を作っています。
開発環境は VisualStudio2019 でC#を使っています。
指定された間隔は 10ミリ秒なんですが、
以下のようなプログラムで得た時刻(timedata)をタイマーをStop後に見たら、30~38ミリ秒間隔位なります。
(確認は Windows10(64bit版)のPCで行っています)// タイマー設定 DispatcherTimer dispatcherTimer = new DispatcherTimer(); dispatcherTimer.Tick += dispatcherTimer_Tick; dispatcherTimer.Interval = TimeSpan.FromMilliseconds(10) timeCnt = 0; // タイマー起動 dispatcherTimer.Start(); void dispatcherTimer_Tick(object sender, object e) { timedata[testCnt++] = DateTime.Now.ToString("yyyyMMddHHmmss.fff"); }
TimeSpan.FromMilliseconds(0) にすると12~18ミリ秒間隔位になるのですが、
デバイスに依存しているようであまり気持ちよくありません。(完成版はタブレットで使う予定です)指定したミリ秒間隔である程度正確(1~2ミリ秒の誤差は許容範囲)にタイマーを動かく方法がありましたらご教授お願いします。
回答
-
本当にミリ秒単位で動かないといけないのでしょうか?
多少周期がずれても、キューに貯まるだけでうまく動くなら、その精度を期待しないで作ったら良いと思います。
ミリ秒単位のシビアな動きを要求されるなら、Windows など搭載した汎用 PC を使うのではなく、特化したデバイスを考える領域になってきます。(参考)
DispatcherTimer は UI スレッドでの動作なので UI スレッド依存で精度は悪い方になります。
ほかのタイマー(参考)を使っても、高い精度は保証されていないと思います。
専用スレッドでループをうまく使えば近しい精度になるかもしれませんが、これも保証された動きではないです。本当はミリ秒単位のシビアさがなく、今よりも周期の頻度を上げたいだけならバックグラウンド系のタイマー、スレッドを考えるところでしょうね。(その代わり、UI を扱えなくなるので同期周りに苦労しますが)
- 編集済み AzuleanMVP, Moderator 2020年5月1日 5:12
- 回答としてマーク Freeプログラマー 2020年5月4日 4:28
すべての返信
-
本当にミリ秒単位で動かないといけないのでしょうか?
多少周期がずれても、キューに貯まるだけでうまく動くなら、その精度を期待しないで作ったら良いと思います。
ミリ秒単位のシビアな動きを要求されるなら、Windows など搭載した汎用 PC を使うのではなく、特化したデバイスを考える領域になってきます。(参考)
DispatcherTimer は UI スレッドでの動作なので UI スレッド依存で精度は悪い方になります。
ほかのタイマー(参考)を使っても、高い精度は保証されていないと思います。
専用スレッドでループをうまく使えば近しい精度になるかもしれませんが、これも保証された動きではないです。本当はミリ秒単位のシビアさがなく、今よりも周期の頻度を上げたいだけならバックグラウンド系のタイマー、スレッドを考えるところでしょうね。(その代わり、UI を扱えなくなるので同期周りに苦労しますが)
- 編集済み AzuleanMVP, Moderator 2020年5月1日 5:12
- 回答としてマーク Freeプログラマー 2020年5月4日 4:28
-
FYI
------------------------------------------------
マルチコアCPUの消費電力はスケジューリングで変わる?
https://ascii.jp/elem/000/000/672/672088/
一般的なパソコンでは、15.6ミリ秒ごとにCPUに割り込みがかかり、
そのタイミングでスケジューラー(ディスパッチャー)が動作して、
より優先順位の高いスレッドがあれば、
そのスレッドを実行する。
------------------------------------------------
Processes, Threads, and Jobs in the Windows Operating System
https://www.microsoftpressstore.com/articles/article.aspx?p=2233328
------------------------------------------------
About Multimedia Timers
https://docs.microsoft.com/en-us/windows/win32/multimedia/about-multimedia-timers
------------------------------------------------
Timer Resolution
https://docs.microsoft.com/ja-jp/windows/win32/multimedia/timer-resolution
------------------------------------------------
timeGetDevCaps function
https://docs.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timegetdevcaps
------------------------------------------------
- 編集済み お馬鹿 2020年5月1日 5:45
-
15.6msという話もありますが、その前提として一般的なモニタが60fps、つまり1秒間に60回しか画面更新しません。そのために16.6ms単位で処理すれば十分という考え方があり、タイマー精度もそれに基づいています。
そのため、ミリ秒間隔で情報を取得したとしても表示することができないということを理解すべきです。
なお、Windowsの各種Timerの精度について調べたことがあります。廃止済みとされているマルチメディアタイマーを使用すれば高い精度が得られるかもしれません。