Поделиться через


Практическое руководство. Использование таймера высокого разрешения

Обновлен: Ноябрь 2007

Некоторые устройства поддерживают таймер высокого разрешения. Такой таймер, если он есть, обеспечивает более точные измерения, чем полученные с помощью свойства TickCount с разрешением 1 мс. В приложениях, где требуется точное измерение времени, таймер высокого разрешения обеспечивает наилучшие результаты. Например, некоторые приложения Direct3D отображают графику плавнее, если анимация основана на таком таймере. Также можно использовать таймер в приложении для определения времени, которое требуется методу или разделу кода для выполнения.

Пример

В этом примере кода используется класс, облегчающий использование таймера высокого разрешения в управляемом коде в Windows CE. Этот пример обладает следующими возможностями.

  • Объявления платформенного вызова для собственных методов в Windows CE.

  • Свойство для получения частоты счетчика высокой точности.

  • Свойство для получения значения счетчика высокой точности.

  • Реализация, поддерживающая свойство TickCount в качестве резервного способа измерения, если функция QueryPerformanceCounter не поддерживается или эмулируется.

  • Пример использования счетчика высокой точности для определения времени операции.

Public Class HiResTimer
    Private isPerfCounterSupported As Boolean = False
    Private timerFrequency As Int64 = 0

    ' Windows CE native library with QueryPerformanceCounter().
    Private Const [lib] As String = "coredll.dll"

    Public Declare Function QueryPerformanceCounter Lib "Coredll.dll" _
    (ByRef count As Int64) As Integer

    Public Declare Function QueryPerformanceFrequency Lib "Coredll.dll" _
    (ByRef timerFrequency As Int64) As Integer    

    Public Sub New() 
        ' Query the high-resolution timer only if it is supported.
        ' A returned frequency of 1000 typically indicates that it is not
        ' supported and is emulated by the OS using the same value that is
        ' returned by Environment.TickCount.
        ' A return value of 0 indicates that the performance counter is
        ' not supported.
        Dim returnVal As Integer = QueryPerformanceFrequency(timerFrequency)

        If returnVal <> 0 AndAlso timerFrequency <> 1000 Then
            ' The performance counter is supported.
            isPerfCounterSupported = True
        Else
            ' The performance counter is not supported. Use
            ' Environment.TickCount instead.
            timerFrequency = 1000
        End If

    End Sub


    Public ReadOnly Property Frequency() As Int64 
        Get
            Return timerFrequency
        End Get
    End Property


    Public ReadOnly Property Value() As Int64 
        Get
            Dim tickCount As Int64 = 0

            If isPerfCounterSupported Then
                ' Get the value here if the counter is supported.
                QueryPerformanceCounter(tickCount)
                Return tickCount
            Else
                ' Otherwise, use Environment.TickCount
                Return CType(Environment.TickCount, Int64)
            End If
        End Get
    End Property


    Shared Sub Main() 
        Dim timer As New HiResTimer()

        ' This example shows how to use the high-resolution counter to 
        ' time an operation. 
        ' Get counter value before the operation starts.
        Dim counterAtStart As Int64 = timer.Value

        ' Perform an operation that takes a measureable amount of time.
        Dim count As Integer
        For count = 0 To 9999
            count += 1
            count -= 1
        Next count

        ' Get counter value after the operation ends.
        Dim counterAtEnd As Int64 = timer.Value

        ' Get time elapsed in tenths of milliseconds
        Dim timeElapsedInTicks As Int64 = counterAtEnd - counterAtStart
        Dim timeElapseInTenthsOfMilliseconds As Int64 = timeElapsedInTicks * 10000 / timer.Frequency


        MessageBox.Show("Time Spent in operation (tenths of ms) " + timeElapseInTenthsOfMilliseconds.ToString + vbLf + "Counter Value At Start: " + counterAtStart.ToString + vbLf + "Counter Value At End : " + counterAtEnd.ToString + vbLf + "Counter Frequency : " + timer.Frequency.ToString)

    End Sub
End Class
public class HiResTimer
{
    private bool isPerfCounterSupported = false;
    private Int64 frequency = 0;

    // Windows CE native library with QueryPerformanceCounter().
    private const string lib = "coredll.dll";
    [DllImport(lib)]
    private static extern int QueryPerformanceCounter(ref Int64 count);
    [DllImport(lib)]
    private static extern int QueryPerformanceFrequency(ref Int64 frequency);

    public HiResTimer()
    {
        // Query the high-resolution timer only if it is supported.
        // A returned frequency of 1000 typically indicates that it is not
        // supported and is emulated by the OS using the same value that is
        // returned by Environment.TickCount.
        // A return value of 0 indicates that the performance counter is
        // not supported.
        int returnVal = QueryPerformanceFrequency(ref frequency);

        if (returnVal != 0 && frequency != 1000)
        {
            // The performance counter is supported.
            isPerfCounterSupported = true;
        }
        else
        {
            // The performance counter is not supported. Use
            // Environment.TickCount instead.
            frequency = 1000;
        }
    }

    public Int64 Frequency
    {
        get
        {
            return frequency;
        }
    }

    public Int64 Value
    {
        get
        {
            Int64 tickCount = 0;

            if (isPerfCounterSupported)
            {
                // Get the value here if the counter is supported.
                QueryPerformanceCounter(ref tickCount);
                return tickCount;
            }
            else
            {
                // Otherwise, use Environment.TickCount.
                return (Int64)Environment.TickCount;
            }
        }
    }

    static void Main()
    {
        HiResTimer timer = new HiResTimer();

        // This example shows how to use the high-resolution counter to 
        // time an operation. 

        // Get counter value before the operation starts.
        Int64 counterAtStart = timer.Value;

        // Perform an operation that takes a measureable amount of time.
        for (int count = 0; count < 10000; count++)
        {
            count++;
            count--;
        }

        // Get counter value when the operation ends.
        Int64 counterAtEnd = timer.Value;

        // Get time elapsed in tenths of a millisecond.
        Int64 timeElapsedInTicks = counterAtEnd - counterAtStart;
        Int64 timeElapseInTenthsOfMilliseconds =
            (timeElapsedInTicks * 10000) / timer.Frequency;

        MessageBox.Show("Time Spent in operation (tenths of ms) "
                       + timeElapseInTenthsOfMilliseconds +
                       "\nCounter Value At Start: " + counterAtStart +
                       "\nCounter Value At End : " + counterAtEnd +
                       "\nCounter Frequency : " + timer.Frequency);
    }
}

Компиляция кода

Для этого примера требуются ссылки на следующие пространства имен:

См. также

Другие ресурсы

Сборка приложений и основные задачи в платформе .NET Compact Framework

Взаимодействие в платформе .NET Compact Framework