1

NTPクライアントを使用してインターネット時刻に同期するマシンがあるので、システムクロックはかなり正確である必要があります。

開発中のアプリケーションがあり、データをリアルタイムでログに記録し、処理してから渡します。私が今やりたいのは、システムクロックに合わせてNミリ秒ごとにそのデータを出力することです。したがって、たとえば、20ミリ秒間隔で実行したい場合、私の出力は次のようになります。

13:15:05:000
13:15:05:020
13:15:05:040
13:15:05:060

ストップウォッチクラスを使用するための提案を見てきましたが、それは特定のタイムスタンプを探すのではなく、期間を測定するだけです。これを行うためのコードは独自のスレッドで実行されているため、比較的ブロックする呼び出しを行う必要がある場合は問題になるはずです。

これを合理的に(1msの精度に近いかそれ以上の精度で)達成する方法についての提案は、非常にありがたく受け取られます。

4

8 に答える 8

2

C ++ / CLRでどれだけうまく機能するかはわかりませんが、マルチメディアタイマーを確認したいと思うかもしれ
ません。Windowsは実際にはリアルタイムではありませんが、これは可能な限り近いものです。

于 2010-03-25T17:18:37.980 に答える
2

期間を短縮すると、timeGetTime()からかなり正確なタイムスタンプを取得できます。戻り値を時計の時刻に変換するには、いくつかの作業が必要です。このサンプルC#コードは、次のアプローチを示しています。

using System;
using System.Runtime.InteropServices;

class Program {
    static void Main(string[] args) {
        timeBeginPeriod(1);
        uint tick0 = timeGetTime();
        var startDate = DateTime.Now;
        uint tick1 = tick0;
        for (int ix = 0; ix < 20; ++ix) {
            uint tick2 = 0;
            do {  // Burn 20 msec
                tick2 = timeGetTime();
            } while (tick2 - tick1 < 20);
            var currDate = startDate.Add(new TimeSpan((tick2 - tick0) * 10000));
            Console.WriteLine(currDate.ToString("HH:mm:ss:ffff"));
            tick1 = tick2;
        }
        timeEndPeriod(1);
        Console.ReadLine();
    }
    [DllImport("winmm.dll")]
    private static extern int timeBeginPeriod(int period);
    [DllImport("winmm.dll")]
    private static extern int timeEndPeriod(int period);
    [DllImport("winmm.dll")]
    private static extern uint timeGetTime();
}

考え直してみると、これは単なる測定です。アクションを定期的に実行するには、timeSetEvent()を使用する必要があります。timeBeginPeriod()を使用している限り、1ミリ秒にかなり近いコールバック期間を取得できます。良い点の1つは、何らかの理由で前のコールバックが遅れたときに自動的に補正することです。

于 2010-03-25T18:18:25.343 に答える
1

最善の策は、インラインアセンブリを使用し、このコードのチャンクをデバイスドライバーとして作成することです。

そのように:

  • 命令数を制御できます
  • アプリケーションの実行が優先されます
于 2010-03-25T17:16:47.763 に答える
1

オペレーティングシステムは他のプロセスからの要求を尊重して実行する必要があるため、最終的には必要なものを保証できません。つまり、プロセスを実行したい瞬間に、他の何かが常にビジー状態になる可能性があります。ただし、を使用timeBeginPeriodして問題を改善し、プロセスをタイムリーに切り替えることができる可能性を高めることができます。また、反復間の待機方法に注意を払うこともできます。常にではありませんがほとんどの時間スリープし、残りの時間はビジーループを使用します。

于 2010-03-25T17:28:12.500 に答える
1

これを2つのスレッドで実行してみてください。1つのスレッドで、このようなものを使用して、ループ内の高精度タイマーを照会します。20msの境界に一致する(またはかなり近い)タイムスタンプを検出したら、使用するタイムスタンプとともに信号をログ出力スレッドに送信します。ログ出力スレッドは、単にシグナルを待ってから、渡されたタイムスタンプを取得し、必要なものをすべて出力します。2つを別々のスレッドに保持すると、ログ出力スレッドがタイマーに干渉しないようになります(これは、基本的にハードウェアタイマー割り込みをエミュレートします。これは、組み込みプラットフォームで行う方法です)。

于 2010-03-25T17:29:09.683 に答える
0

CreateWaitableTimer / SetWaitableTimerと優先度の高いスレッドは、約1msの精度である必要があります。例の出力のミリ秒フィールドが4桁である理由はわかりませんが、最大値は999です(1000ミリ秒= 1秒であるため)。

于 2010-03-25T17:25:55.237 に答える
0

あなたが言ったように、これは完璧である必要はないので、できることがいくつかあります。

私の知る限り、特定の時刻と同期するタイマーはありません。したがって、次回の時間を計算し、その特定の時間にタイマーをスケジュールする必要があります。タイマーがデルタをサポートしているだけの場合、それは簡単に計算できますが、デルタを計算してからタイマーがカーネルに入るまでの間にCPUを簡単にキックオフできるため、エラーが増えます。

すでに指摘したように、WindowsはリアルタイムOSではありません。したがって、タイマーを「:0010」でオフにするようにスケジュールした場合でも、コードはその時間のかなり後まで実行されない可能性があることを想定する必要があります(たとえば、「:0540」)。これらの問題を適切に処理する限り、問題はありません。

于 2010-03-25T17:30:20.547 に答える
0

20msは、Windowsのタイムスライスの長さです。Intimeのような何らかのRTアドオンがなければ、Windowsで1msの種類のタイミングを確実にヒットする方法はありません。適切なウィンドウでは、オプションはWaitForSingleObject、SleepEx、およびビジーループだと思います。

于 2010-03-25T17:36:24.380 に答える