0

タイマーに奇妙な問題があります。私の知る限り、タイマーの interval プロパティは、timer_Tick イベントが発生するループ間の遅延を示します。

Visual Basic でプログラミングする前に、正確な署名 (15 および 16 ミリ秒の遅延) でこの問題が発生しました。私が作成したすべてのタイマーは、15 または 16 ミリ秒の遅延でティック イベントを発生させます。たとえば、タイマーの間隔を 1 に設定した場合 (つまり、ティック イベントが 1 秒間に 1000 回発生する必要があります)、イベントは 1 秒間に 62 回から 66 回発生します (つまり、1000/16 から 1000/15 です)。 )。

私は 5 年前から VB アプリケーションを開発しており、常にこの問題を抱えていました (つまり、AMD と Intel の両方のプロセッサを搭載したいくつかの異なるシステムでこの問題が発生したことも意味します)。

TickCount メソッド (VB の GetTickCount API と C# の Environment.TickCount) に基づいて tick イベントが発生するたびに時間差を計算することで、回避策を実行してこの問題を解決することができました。

*TickCount は、時間システムが開始されてから経過したミリ秒数です。

問題をよりよく理解するために、(タイマーのように) 実行されてからの秒数をカウントする Windows アプリケーションを作成しました。Tick イベントが発生するたびに、TickCount と通常の加算の両方に依存します。また、TickCount の現在の値から TickCount の最後の値を差し引いて、タイマーの遅延を計算します (タイマーが 1 秒間に 1000 回起動された場合、TickCount の差は毎回 1 になるため、つまり、遅延はありませんが、差が 1 を超える場合は、タイマーの tick イベントが発生するたびに遅延が生じます)。

コードは次のとおりです。

public partial class Form1 : Form
{
    int localTime = 0, systemTime = 0, baseSystemTime = 0, lastSystemTime = 0;
    public Form1()
    {
        InitializeComponent();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        // Calculate time based on TickCount
        if (baseSystemTime == 0)
            baseSystemTime = Environment.TickCount;

        systemTime = Environment.TickCount - baseSystemTime;
        label2.Text ="System Time: " + ((systemTime / 1000) / 60).ToString() + ":" + ((systemTime / 1000) % 60).ToString();

        // Calculate time based on timer1_Tick
        localTime++;
        label1.Text = "Application Time: " + ((localTime / 1000) / 60).ToString() + ":" + ((localTime / 1000) % 60).ToString();

        // Calculate the delay
        if (lastSystemTime > 0)
        {
            label3.Text = "Delay: " + (Environment.TickCount - lastSystemTime).ToString() + " ms";
        }

        lastSystemTime = Environment.TickCount;
    }
}

また、ソリューション全体をここにアップロードしました: http://ramt.in/test/TimerDelay.zip

これはアプリケーションのスクリーンショットです (15 ミリ秒の遅延と、実際には 17 秒が経過している間にアプリケーションによって 1 秒がカウントされます!):

スクリーンショット

ソリューションは 50kb しかないので、自由にダウンロードして実行し、私と同じ結果が得られるかどうかを確認してください。同じなら、Microsoft ワールドのタイマー クラスに問題があります。

しかし、もっと重要なことは、この遅延の原因について何か知っている人がいる場合は、その知識を私と共有してください.

4

2 に答える 2

1

これは、C# や VB ではなく、システムの問題です。Stopwatchシステムのおもちゃがクラスと 2 つのプロパティを使用できる精度を確認するには

  1. IsHighResolution -The timer used by the Stopwatch class depends on the system hardware and operating system. IsHighResolution is true if the Stopwatch timer is based on a high-resolution performance counter. Otherwise, IsHighResolution is false, which indicates that the Stopwatch timer is based on the system timer.
  2. 周波数

MSDNの次のコードは、それがどのように機能するかを示しています

public static void DisplayTimerProperties()
{
    // Display the timer frequency and resolution. 
    if (Stopwatch.IsHighResolution)
    {
        Console.WriteLine("Operations timed using the system's high-resolution performance counter.");
    }
    else 
    {
        Console.WriteLine("Operations timed using the DateTime class.");
    }

    long frequency = Stopwatch.Frequency;
    Console.WriteLine("  Timer frequency in ticks per second = {0}",
        frequency);
    long nanosecPerTick = (1000L*1000L*1000L) / frequency;
    Console.WriteLine("  Timer is accurate within {0} nanoseconds", 
        nanosecPerTick);
}

アップデート

コードでエラーも発生しました:

        // Calculate time based on timer1_Tick
        localTime++;
        label1.Text = "Application Time: " + ((localTime / 1000) / 60).ToString() + ":" + ((localTime / 1000) % 60).ToString();

このセリフは過ぎ去った時間に何もありません。実行された回数のみを計算しtimer1_Tickます。1 ミリ秒間隔は、Windows フォーム タイマーには小さすぎます。ここでこれについて読むことができます:タイマーは間隔よりも10ミリ秒かかります

より正確なタイマーが必要な場合は、この記事を参照してください。 Microsecond and Millisecond C# Timer

于 2015-05-02T06:52:31.720 に答える