5580


MFCで１秒周期で処理を行うプログラムを作成していますが、  
標準のタイマーを利用するとほぼ毎秒に10ミリ秒〜15ミリ秒のずれが発生します。

マルチメディアタイマーを利用するとタイマーの精度問題は解決できますか  
他のライブラリと相性が悪く他ライブラリがクラッシュしてしまいます。  
プロジェクトの関係で他ライブラリは変更できません。

標準のタイマーの精度は上げる方法はありますか？  
あるいは標準のタイマーのズレを補正する方法はありますか？

ご教授よろしくお願いいたします。

-- 2015/02/01 --  
遅くなりましたが、時間がなかったのでとりあえずタイマーのズレを補正する方法で対応しました。  
補正の方法としては  
最初のマイマーのセットのタイミングで、基準時間と実行回数を設定し、  
基準時間より総ずれた時間とズレの平均値を計算し次のタイマーにその分を減算してセットしています。  
しばらく動かして見ましたが、ほぼ安定して動作しています。  
あとは1日1回基準時間と実行回数を初期化するロジックを追加すれば問題は解決できると思います。


CC BY-SA 3.0
2015-01-29T13:13:14.633
5576
2015-02-01T04:39:47.257
2015-02-01T04:39:47.257
7642
7642
question
windows c++ mfc
MFCでの標準タイマーの精度をあげる方法ありますか？


> 標準のタイマーを利用するとほぼ毎秒に10ミリ秒〜15ミリ秒のずれが発生

Windows OSのシステムクロックは15.6ミリ秒の分解能しかもたないため（Windows
7）、記載のような事象が発生します。高精度タイマが必要な場合は、仰るように[マルチメディアタイマ](https://msdn.microsoft.com/ja-
jp/library/cc428795.aspx)を利用すべきです。

> 標準のタイマーの精度は上げる方法はありますか？  
>  あるいは標準のタイマーのズレを補正する方法はありますか？

直接的には不可能かと思われます。ただし、[`timeBeginPeriod`](https://msdn.microsoft.com/ja-
jp/library/cc428791.aspx)
設定の影響をうけて、システム全体のタイマ精度が変化します。他プロセスの動作にも影響を与えるため、その動作が仕様として望ましいか否かは留意してください。

タイマ精度に関しては、Microsoft社から出ている "[Timers, Timer Resolution, and Development of
Efficient
Code](http://download.microsoft.com/download/3/0/2/3027D574-C433-412A-A8B6-5E0A75D5B237/Timer-
Resolution.docx)"(docx) が詳しいです。

高精度タイマとして、[`QueryPerformanceCounter`](https://msdn.microsoft.com/ja-
jp/library/cc410966.aspx)(QPC)
という選択肢もあります。QPCはナノ秒オーダーの分解能を持ちますが、長時間計測に用いると累積誤差がある気がします（これは個人的な経験則ですが…）。また、Windows
OS世代や実行環境によって動作が微妙に異なることもあります。

QPCに関する詳細はMSDN "[Acquiring high-resolution time
stamps](https://msdn.microsoft.com/en-us/library/dn553408.aspx)" を参照下さい。


CC BY-SA 3.0
2015-01-29T14:43:58.923
5580
2015-01-30T00:28:34.877
2015-01-30T00:28:34.877
49
49
5576
answer


標準のタイマー及びその元になっているWindows
APIのSetTimerはGUIスレッド上で動作します。それ以外の全てのタイマーはGUIスレッド上で動作させることはできません（動作させた時点でGUIが止まってしまいます）。

マルチメディアタイマーとの相性が悪い、「本当はバックグラウンド処理向け」とお考えのようですが、GUIスレッドでないことが原因のように感じています。  
具体的にライブラリを確認してみないことにはわかりませんが、OCXとのことですしGUIスレッド上での実行が暗黙的に要求されている可能性はあります。

試しにスレッドを１つ作り、そこでSleep(1000)しながら呼び出すループを作ってみてはどうでしょうか？

yohjpさんの紹介していないタイマーとして例えばThread Pool Timerがあります。Windows
Vista以降に限定されますが、[CreateThreadpoolTimer()](https://msdn.microsoft.com/en-
us/library/ms682466\(v=vs.85\).aspx)でコールバックを指定してタイマーオブジェクトを作成し、[SetThreadpoolTimer()](https://msdn.microsoft.com/en-
us/library/ms686271\(v=vs.85\).aspx)でタイマーをスタートします。[CloseThreadpoolWork()](https://msdn.microsoft.com/en-
us/library/ms682043\(v=vs.85\).aspx)で終了できます。これですとHNS; 100ナノ秒単位で指定できます。


CC BY-SA 3.0
2015-01-30T09:00:31.860
5615
2015-01-30T09:00:31.860
4236
5576
answer