# Visual Basic > Games and Graphics Programming > Game Demos >  [Vb.Net] Managed Game Loop

## dday9

*Description*
Some people want the ease of use from a timer but want the accuracy from a game loop. Well this code here does just that. Use it like a timer, but expect high precision accuracy that automatically matches the computer monitor's refresh rate.

*Prerequisites*
Simply add the _System.Management_ DLL to your references. If you computer does not support the _QueryPerformance_ API's then an exception will be thrown.

*Code*


```
Option Strict On
Option Explicit On
<System.ComponentModel.DefaultEvent("Tick")> _
Public Class GameLoop
    Inherits System.ComponentModel.Component

    Private frequency As Long
    Private waitThread As Threading.Thread

#Region "Api"

    Private Declare Function QueryPerformanceCounter Lib "kernel32" (ByRef lpPerformanceCount As Long) As Integer
    Private Declare Function QueryPerformanceFrequency Lib "kernel32" (ByRef lpFrequency As Long) As Integer

#End Region

#Region "Events"

    Public Event Tick(ByVal sender As Object, ByVal e As EventArgs)

#End Region

#Region "Methods"

    Private Sub CheckCompatibility()
        Dim test As Long
        If Not CBool(QueryPerformanceCounter(test)) Then
            Throw New Exception("High-resolution counter is not supported for this computer.")
        End If
    End Sub

    Private Function GetRefreshRate() As Double
        Dim query As System.Management.SelectQuery = New System.Management.SelectQuery("Win32_VideoController")

        For Each mo As System.Management.ManagementObject In New System.Management.ManagementObjectSearcher(query).Get
            Dim currentRate As Object = mo("CurrentRefreshRate")
            If currentRate IsNot Nothing Then
                Return CDbl(currentRate)
            End If
        Next

        Return Nothing
    End Function

    Public Sub Start()
        pEnabled = True
        waitThread = New Threading.Thread(AddressOf Wait)
        waitThread.IsBackground = True
        waitThread.Start()
    End Sub

    Public Sub [Stop]()
        Me.Enabled = False
    End Sub

    Private Sub Wait()
        Dim counter1, counter2 As Long
        QueryPerformanceCounter(counter1)

        Do
            QueryPerformanceCounter(counter2)
        Loop Until (counter2 - counter1) / (frequency / 1000) >= 1000 / rate

        RaiseEvent Tick(Me, EventArgs.Empty)

        Console.WriteLine((counter2 - counter1) / (frequency / 1000))

        If pEnabled Then
            waitThread = New Threading.Thread(AddressOf Wait)
            waitThread.IsBackground = True
            waitThread.Start()
        End If

    End Sub

#End Region

#Region "New Constructor"

    Sub New()
        Call CheckCompatibility()
        QueryPerformanceFrequency(frequency)
        rate = GetRefreshRate()
    End Sub

#End Region

#Region "Properties"

    Private pEnabled As Boolean
    <System.ComponentModel.Description("Gets or sets a value indicating whether the GameLoop should raise the Tick event.")> _
    Public Property Enabled() As Boolean
        Get
            Return pEnabled
        End Get
        Set(ByVal value As Boolean)
            If pEnabled <> value Then
                pEnabled = value
                If pEnabled Then RaiseEvent Tick(Me, EventArgs.Empty)
            End If
        End Set
    End Property

    Private rate As Double
    <System.ComponentModel.Description("Gets or sets a value indicating the refresh rate of the computer's monitor.")> _
    Public ReadOnly Property RefreshRate() As Double
        Get
            Return rate
        End Get
    End Property

#End Region

End Class
```

*Acknowledgements*
_Jacob Roman_ - Showing me the QueryPerformance API's
_TnTinMN_ - Helping with getting the refresh rate of the monitor

----------


## boops boops

Hi dday,
This would be a really useful timer but I can't get it to work as described. To  test it, I dragged a GameLoop component onto a form with a button, and coded the form as follows:


```
	Private sw As Stopwatch
	Dim prevMilliseconds As Integer

	Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
		With GameLoop1
			Console.WriteLine(.RefreshRate)
			sw = Stopwatch.StartNew
			.Start()
		End With
	End Sub

	Private Sub GameLoop1_Tick(sender As Object, e As System.EventArgs) Handles GameLoop1.Tick
		Dim s As Integer = CInt(sw.ElapsedMilliseconds)
		Console.WriteLine(s - prevMilliseconds)
		prevMilliseconds = s
	End Sub
```

The output shows the Tick interval alternating between an exact-looking 16.66... milliseconds and a rather random interval of somewhere between 20 and 120 milliseconds, for example:


```
16,6667161647157
24
16,6666973679882
88
16,6669718002096
44
17,9118978585828
64
16,6671447301025
53
16,6669417254456
```

(excusez le decimal comma :Stick Out Tongue: )
Of course, this could conceivably be due to my somewhat antiquated hardware (with WinXP no less) or maybe I have made a mistake somewhere. What result do you get when you run the same test?

BB

----------


## dday9

What I have found is that the QueryPerformance API's are very hardware intensive, so if you do not have up-to-date hardware then it can run sporadically.

Another thing that I noticed is that if you're running a dual monitor, then you'll get optimal results by running the program on the primary screen.

----------

