locked
Timer Issues RRS feed

  • General discussion

  • Using the Timer in v0.4 can cause some problems if the events it raises do not fully complete before it is next triggered. 

    Also, since all variables (including Brush and Pen attributes etc) are static (global) they are shared between all subroutines.  If the timer event causes more than one operation to be called at the same time, then problems can occur when a variable is changing in one part of the code while being used in another.

    For example this causes problems on my PC (reasonably fast).

    Timer.Interval = 10
    Timer.Tick = OnTimer
    GraphicsWindow.Show()
    
    Sub OnTimer
      DoOneThing()
      DoAnotherThing()
    EndSub
    
    Sub DoOneThing
      GraphicsWindow.BrushColor = "Red"
      For i = 1 To 20
        x = 10*i
        y = 20*i
        size = 3*i
        GraphicsWindow.FillEllipse(x,y,size,size)
      EndFor
    EndSub
        
    Sub DoAnotherThing
      GraphicsWindow.BrushColor = "Blue"
      For i = 1 To 20
        x = 200-10*i
        y = 300-20*i
        size = 2*i
        GraphicsWindow.FillRectangle(x,y,size,size)
      EndFor
    EndSub

    I have found that using the Program.Delay inside an infinite main while loop always performs any actions consecutively and hence works.

    I recommend this type of method to handle rapid updates such as motion.

    For example this works as expected.

    GraphicsWindow.Show()
    
    While ("true")
      DoOneThing()
      DoAnotherThing()
      Program.Delay(10)
    EndWhile
    
    Sub DoOneThing
      GraphicsWindow.BrushColor = "Red"
      For i = 1 To 20
        x = 10*i
        y = 20*i
        size = 3*i
        GraphicsWindow.FillEllipse(x,y,size,size)
      EndFor
    EndSub
       
    Sub DoAnotherThing
      GraphicsWindow.BrushColor = "Blue"
      For i = 1 To 20
        x = 200-10*i
        y = 300-20*i
        size = 2*i
        GraphicsWindow.FillRectangle(x,y,size,size)
      EndFor
    EndSub
    

    Note, this is not specific to calling subroutines from the timer event.  The following crashes for the same reason:

    Timer.Interval = 10
    Timer.Tick = OnTimer

    Sub OnTimer
    Sound.PlayBellRing()
    EndSub


    It all depends on making sure everything in the timer event is completed before it is started again and will vary from PC to PC depending on its performance and lead to difficult debugging in rapid event calling typical for motion games.



    Monday, April 27, 2009 6:22 PM

All replies

  • Using the Timer in v0.4 can cause some problems if the events it raises do not fully complete before it is next triggered. 
    ...
    It all depends on making sure everything in the timer event is completed before it is started again and will vary from PC to PC depending on its performance and lead to difficult debugging in rapid event calling typical for motion games.


    I perform such an operation with SmallBasic.SetInterval in my extension.
    If you don't you can get crazy result as you showned it.

    But then, you can't use a true timer as it's done in SmallBasic. My extension uses this code, maybe it can helps the SBTeam to see what you mean:

        Friend Class ThreadStart
            Public S As SmallBasicCallback
            Public TID As Integer
            Public TimeToWait As Integer = 0
            Public Times As Integer = 1
    
            ''' <summary>
            ''' Internal function (not supposed to be called by Small Basic)
            ''' </summary>
            ''' <remarks>You should not see this function in Small Basic</remarks>
            Public Sub Start()
                Try
                    If Times = -1 Then
                        Dim EndTime As Date
                        Dim StartTime As Date
                        Dim TimeToWait As Integer = Me.TimeToWait
                        While True
                            Threading.Thread.Sleep(TimeToWait)
    
                            StartTime = Date.Now
                            S()
                            EndTime = Date.Now
    
                            TimeToWait = System.Math.Max(Me.TimeToWait - CInt((EndTime - StartTime).TotalMilliseconds), 0)
                        End While
                    ElseIf Times = 0 Then
                        Exit Sub
                    ElseIf Times = 1 Then
                        Threading.Thread.Sleep(TimeToWait) : S()
                    Else
                        Dim EndTime As Date
                        Dim StartTime As Date
                        Dim TimeToWait As Integer = Me.TimeToWait
                        For X = 0 To Times - 1
                            Threading.Thread.Sleep(TimeToWait)
    
                            StartTime = Date.Now
                            S()
                            EndTime = Date.Now
    
                            TimeToWait = Me.TimeToWait - CInt((EndTime - StartTime).TotalMilliseconds)
                        Next
                    End If
                Catch ex As Exception
                    ' MessageBox.Show(ex.ToString())
                Finally
                    _Asyncs(TID) = Nothing
                End Try
            End Sub
        End Class
    

    This implementation calls the sub each TimeToWait (= Interval), but the time between to call can't be smaller than the time the sub needs to run. If you ask that your sub gets called each 1ms but these sub needs 10ms to run, you'll have a "effective" interval of 10ms. It also prevents having too many opened threads...

    Fremy - Developer in VB.NET, C# and JScript ... - Feel free to try my extension
    Monday, April 27, 2009 6:59 PM
  • I guess all of the standard small basic events are not tread safe.  I can create problems with MouseMove etc.  Using your extension is a solution for those using it, but many won't be.

    Without using your extension, events can be made to work using the event call to only to set a flag or variable - not do the work.  Then do the work (depending on the event flags set) inside a main consecutive tread safe loop (e.g While ("true") ... EndWhile) so the events get processed consecutively as CPU permits.

    The conclusion is for users to be aware of the issue and either use your extension or the type of method I outlined, while hopefully the SB development team will look at it sometime.
    Monday, April 27, 2009 8:16 PM
  • litdev & Fremy,

    Thanks for bringing this up.  I've created a bug in our database and we'll look into fixing this for v0.5.

    Monday, April 27, 2009 9:54 PM