12

System.Timers.Timer オブジェクトを使用して、メイン フォーム ( Windows フォーム、C#)によって処理されるイベントを発生させるアプリケーションがあります。私の問題は、.Interval をどれだけ短く (1 ミリ秒まで) 設定しても、1 秒あたり最大 64 回になることです。

Forms タイマーには 55 ミリ秒の精度制限があることは知っていますが、これは System.Timer のバリアントであり、Forms のバリアントではありません。

アプリケーションは 1% の CPU を使用するため、CPU バウンドではありません。したがって、それが行っていることは次のとおりです。

  • タイマーを 1ms に設定します
  • イベントが発生したら、_Count 変数をインクリメントします
  • もう一度 1&nsp;ms に設定して繰り返します

_Count は、他に行う作業がない場合でも、1 秒間に最大 64 回インクリメントされます。

これは「再生」アプリケーションであり、パケット間のわずか 1 ~ 2 ミリ秒の遅延で着信パケットを複製する必要があるため、1 秒間に 1000 回程度確実に発火できるものが必要です (ただし、 CPUバウンドでした、私はそうではありません)。

何かご意見は?

4

3 に答える 3

4

マルチメディア タイマーを試してみてください。ハードウェア プラットフォームで最大限の精度が得られます。これらのタイマーは、他のタイマー サービスよりも高い解像度でイベントをスケジュールします。

タイマーの解像度を設定し、タイマーを開始および停止するには、次の Win API 関数が必要です。

[DllImport("winmm.dll")]
private static extern int timeGetDevCaps(ref TimerCaps caps, int sizeOfTimerCaps);

[DllImport("winmm.dll")]
private static extern int timeSetEvent(int delay, int resolution, TimeProc proc, int user, int mode);

[DllImport("winmm.dll")]
private static extern int timeKillEvent(int id);

コールバック デリゲートも必要です。

delegate void TimeProc(int id, int msg, int user, int param1, int param2);

およびタイマー機能の構造

[StructLayout(LayoutKind.Sequential)]
public struct TimerCaps
{
    public int periodMin;
    public int periodMax;
}

使用法:

TimerCaps caps = new TimerCaps();
// provides min and max period 
timeGetDevCaps(ref caps, Marshal.SizeOf(caps));
int period = 1;
int resolution = 1;
int mode = 0; // 0 for periodic, 1 for single event
timeSetEvent(period, resolution, new TimeProc(TimerCallback), 0, mode);

そしてコールバック:

void TimerCallback(int id, int msg, int user, int param1, int param2)
{
    // occurs every 1 ms
}
于 2012-11-23T00:13:54.697 に答える
3

デザインにこだわることができます。システム割り込み頻度を最大頻度で実行するように設定するだけで済みます。これを取得するには、コード内の任意の場所で次のコードを実行するだけです:

#define TARGET_RESOLUTION 1         // 1-millisecond target resolution

TIMECAPS tc;
UINT     wTimerRes;

if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) 
{
    // Error; application can't continue.
}

wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
timeBeginPeriod(wTimerRes); 

これにより、システムの割り込み期間が最大の頻度で実行されます。これはシステム全体の動作であるため、別のプロセスで実行されることもあります。使用することを忘れないでください

MMRESULT timeEndPeriod(wTimerRes );

完了したら、リソースを解放し、割り込み期間をデフォルトにリセットします。詳細については、マルチメディア タイマーを参照してください。

timeBeginPeriodへの各呼び出しを への呼び出しと一致させtimeEndPeriod、両方の呼び出しで同じ最小解像度を指定する必要があります。timeBeginPeriod各呼び出しが への呼び出しと一致する限り、アプリケーションは複数の呼び出しを行うことができますtimeEndPeriod

その結果、タイマーの粒度が向上するため、すべてのタイマー (現在の設計を含む) がより高い周波数で動作します。ほとんどのハードウェアで 1 ミリ秒の粒度を取得できます。

以下は、 2 つの異なるハードウェア セットアップ (A+B) のさまざまな設定で得られた割り込み周期のリストです。wTimerRes

ActualResolution (割り込み期間) と wTimerRes の設定

1 ms が理論値であることは容易にわかります。ActualResolution は 100 ns 単位で与えられます。9,766 は 0.9766 ミリ秒を表し、1 秒あたり 1024 の割り込みです。(実際には、9,7656.25 100 ns 単位になる 0.9765625 である必要がありますが、その精度は明らかに整数に適合しないため、システムによって丸められます。)

timeGetDevCapsまた、ig プラットフォーム A が( ~ の範囲の値)によって返されるすべての期間範囲を実際にサポートしていないことも明らかになりwPeriodMinますwPeriodMin

概要:マルチメディア タイマー インターフェイスを使用して、システム全体の割り込み頻度を変更できます。結果として、すべてのタイマーの粒度が変更されます。また、システム時間の更新もそれに応じて変更され、より頻繁に、より小さなステップで増分されます。ただし:実際の動作は、基盤となるハードウェアによって異なります。このハードウェアへの依存は、Windows 7 と Windows 8 の導入以降、タイミングの新しいスキームが導入されて以来、大幅に小さくなっています。

于 2012-11-23T09:34:20.157 に答える