Nefariis
Nefariis

Reputation: 3549

Two timers running simultaneously and independently

First of all, I just wanted to say thanks for all the help given in the past couple weeks. I've learned a ton and my program has been saving me hours and hours of work every day.

I want to expand it a little bit and add a second timer that runs parallel to the first timer, but is not affected in any way shape or form by the first timer.

I've tried nesting the second loop in the first loop but the second loop takes 3 seconds to complete (I use thread.sleep(3000)), so I found that it froze the first loop till the second loop finishes. I was reading about system threading (System.Timers.Timer) and it seems like that is the route I want to go.

I wrote this quick as an example:

This assumes that I added a windows timer control as timer1

Option Strict On
Imports System
Imports System.Timers

Public Class form1

  Private Shared timer2 As System.Timers.Timer
  timer2 = New System.Timers.Timer
  AddHandler timer2.Elapsed, AddressOf OnTimedEvent

  Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
                           Handles Button1.Click
    timer1.Interval = 1000
    timer1.enabled = true
    timer2.Interval = 5000
    timer2.Enabled = True
  End sub

  Public Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) _
                         Handles Timer1.Tick
  'code for timer1 here
  End Sub

  Private Shared Sub OnTimedEvent(source As Object, e As ElapsedEventArgs)
    'code for timer2 here
  End Sub

End Class 

Does this even make sense?... and again I can't use the timer1 to set off the second round of events because of the thread.sleep. I was hoping that the code above puts the second thread to sleep while the windows.form.timer continues on ticking every 1000 ms

Upvotes: 2

Views: 16487

Answers (3)

dbasnett
dbasnett

Reputation: 11773

Public Class Form1
    'a timer that fires periodically
    Dim WithEvents aTimer As New System.Threading.Timer(AddressOf TickTock, Nothing, 0, 500)
    'a stopwatch for each event
    Dim swEV1 As New Stopwatch
    Dim swEV2 As New Stopwatch
    'how long between executions
    Dim ev1Time As New TimeSpan(0, 0, 1)
    Dim ev2Time As New TimeSpan(0, 0, 5)

    'test
    Private Sub Button1_Click(sender As System.Object, _
                              e As System.EventArgs) Handles Button1.Click
        Button1.Enabled = False
        'start the test
        swEV1.Start()
        swEV2.Start()
    End Sub

    Dim ev1 As New Threading.Thread(AddressOf event1)
    Dim ev2 As New Threading.Thread(AddressOf event2)

    Private Sub TickTock(state As Object)
        If swEV1.IsRunning Then
            'check the elapsed time and run the thread when needed
            'only one thread per event is allowed to run
            If swEV1.Elapsed >= ev1Time Then
                If Not ev1.IsAlive Then
                    swEV1.Reset() 'reset the stopwatch
                    swEV1.Start()
                    ev1 = New Threading.Thread(AddressOf event1)
                    ev1.IsBackground = True
                    ev1.Start()
                End If
            End If

            If swEV2.Elapsed >= ev2Time Then
                If Not ev2.IsAlive Then
                    swEV2.Reset()
                    swEV2.Start()
                    ev2 = New Threading.Thread(AddressOf event2)
                    ev2.IsBackground = True
                    ev2.Start()
                End If
            End If

        End If
    End Sub

    Private Sub event1()
        Debug.WriteLine("EV1 " & DateTime.Now.ToString)
        Threading.Thread.Sleep(500) 'simulate work
    End Sub

    Private Sub event2()
        Debug.WriteLine("EV2 " & DateTime.Now.ToString)
        Threading.Thread.Sleep(3000) 'simulate work
    End Sub


End Class

Upvotes: 3

Matt Wilko
Matt Wilko

Reputation: 27342

You can easily have two (or more) timers on you form. You seem to have a mixture of a timer on the form and a timer that you have created programatically. So the example I have given is to create both of them programatically at runtime.

Define your timer objects in your form:

Private Shared timer1 As System.Timers.Timer
Private Shared timer2 As System.Timers.Timer

Define Two Handlers for the Elapsed Events:

Public Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
'code for timer1 here
end sub

Public Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
'code for timer2 here
end sub

Then in your button click you can add the handlers and start the timers:

Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    'Add handlers programatically
    AddHandler timer1.Elapsed, AddressOf Timer1_Tick
    AddHandler timer2.Elapsed, AddressOf Timer2_Tick

    'Set up the timer intervals and start them
    timer1.Interval = 1000
    timer1.enabled = true
    timer2.Interval = 5000
    timer2.Enabled = True

End sub

Also it is worth reading about the different types of timers available to you in .NET

Upvotes: 0

Nicholas
Nicholas

Reputation: 754

I had some really bad experiences with System.Timers.Timer about e.g. Timer-Event not called.

I would recommend the System.Threading.Timer (Also because as far as I know the System.Timers.Timer is only a wrapper for the Threading.Timer

Here is an example of how I usually implement Timers

Note that I always start the Timer with the Change-Method Once and restart it in the Finally Block of the Callback Method to prevent multiple parallel Callbacks of the same Timer-Callback-Method.

Public Class Form1

   Private _Timer1 As System.Threading.Timer
   Private _Timer2 As System.Threading.Timer

   Public Sub New()

      ' This call is required by the designer.
      InitializeComponent()

      ' Add any initialization after the InitializeComponent() call.
      _Timer1 = New System.Threading.Timer(AddressOf Timer1_Callback)
      _Timer2 = New System.Threading.Timer(AddressOf Timer2_Callback)

   End Sub

   Private Sub Timer1_Callback(ByVal state As Object)
      Try

         'code for timer1 here

      Catch ex As Exception
         'Do your errorhandling
      Finally
         'Start with a delay. Just call the Callback once
         _Timer1.Change(1000, System.Threading.Timeout.Infinite)
      End Try
   End Sub
   Private Sub Timer2_Callback(ByVal state As Object)
      Try

         'code for timer2 here

      Catch ex As Exception
         'Do your errorhandling
      Finally
         'Start with a delay. Just call the Callback once
         _Timer2.Change(5000, System.Threading.Timeout.Infinite)
      End Try
   End Sub

   Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
      Try
         'Start with a delay. Just call the Callback once
         _Timer1.Change(1000, System.Threading.Timeout.Infinite)
         _Timer2.Change(5000, System.Threading.Timeout.Infinite)
      Catch ex As Exception
         'Do your errorhandling
      End Try
   End Sub
End Class

Upvotes: 0

Related Questions