3


0

Windowsの待機可能タイマーの問題(timeSetEventおよびCreateTimerQueueTimer)

アプリケーションで高解像度(1ミリ秒よりも正確)のタイミングが必要です。 Windowsの待機可能タイマーはミリ秒単位の精度です(または作成できます)が、たとえば35.7142857141ミリ秒の正確な周期性が必要な場合、36ミリ秒の期間の待機可能タイマーでさえ、すぐに同期しなくなります。

この問題に対する私の「解決策」は(皮肉な引用で、正しく動作しないため)一連のワンショットタイマーを使用して、各タイマーの有効期限を使用して次のタイマーを呼び出すことです。 通常、このようなプロセスは時間の経過とともに累積エラーの影響を受けますが、各タイマーコールバックで現在の時間を確認し( `System.Diagnostics.Stopwatch`を使用)、これを使用して次のタイマーの期間を計算します(そのため、タイマーが少し遅れて期限切れになった場合、次のタイマーは自動的に補正の期間が短くなります)。

これは期待どおりに機能しますが、10〜15秒後にタイマーシステムが動きを止めたように見え、タイマーコールバックがあちこちで25〜100ミリ秒遅れて到着するようです。 数秒後、問題はなくなり、すべてが10〜15秒間スムーズに実行され、その後再びst音が発生します。

「ストップウォッチ」を使用して各タイマー期間を設定しているため、各タイマーコールバックの到着時間を監視するためにも使用しています。 スムーズな実行期間中、間隔のほとんど(おそらく95%)は35ミリ秒または36ミリ秒であり、予想される35.7142857143から5ミリ秒を超える間隔はありません。

「グリッチ」ストレッチの間、間隔の分布は非常に小さい数が非常に大きいことを除いて、ほぼ同じです(60ミリ秒を超えるカップルと、おそらく3秒のストレッチ中に100ミリ秒より長い1つまたは2つ)。 このst音は非常に顕著であり、可能であれば修正しようとしています。

高解像度のタイマーには、 winmm.dll`の非常にアンティークな timeSetEvent() マルチメディアタイマーを使用していました。 この問題を追求して、 `CreateTimerQueueTimer`を(高解像度を設定する timeBeginPeriod`とともに)使用するように切り替えましたが、両方のタイマーメカニズムで同じ問題が発生しています。 タイマーが実行されるスレッドを決定する「CreateTimerQueueTimer」のさまざまなフラグを試してみましたが、どのような場合でもst音が表示されます。

これは、この方法でタイマーを使用する場合の基本的な問題ですか? 各ワンショットタイマーを使用して次を呼び出します)? もしそうなら、代替手段はありますか? 私が検討していたことの1つは、タイマーをリセットする必要がある前に、連続する1ミリ秒の精度のティックが、任意の精度制限内に保持するかどうかを決定することでした。 したがって、たとえば、35.71428の期間が必要な場合、36ミリ秒のタイマーを5ミリ秒オフにする前に15回経過させ、それを強制終了して新しいタイマーを開始できます。

2 Answer


3


NETの制限を考えると、良いアプローチがあると思います。 プロセスの優先順位は何ですか? 他のプロセスがディスクアクティビティを実行しないようにするには、通常よりも高くする必要があると考えています。

私は、ここで.NETフレームワークが最善のソリューションではないことに、ヘンクに同意します。 ガベージコレクションが発生すると、オブジェクトの解放、ヒープの圧縮などに時間がかかる場合があります。

お使いのOSは何ですか? また、リアルタイムOSが最善の解決策であるというヘンクにも同意します。 私が読んだことによると、Windows CEはリアルタイムOSとして適格ですが、これ以上コメントすることはできません。


1


タイマーは安くはないので、1msタイマーを使用して35.7タイマーに近づけることで、ここで余計に食べてしまいます。 私はあなたがPC自体で達成できることの限界にいると思う。 +私は、より長い期間のタイマー(35または36)に行き、ストップウォッチタイマーで修正します。

そして、いくつかの論争を始めるために、.NETフレームワークがこの種のタスクに最も適したプラットフォームであるかどうかはわかりません。 GCが要求にどのように適合するか考えましたか?