Question Issue for a Nested Timer Class

Raffaele

New member
Joined
Aug 19, 2023
Messages
3
Programming Experience
10+
Hi, I'm trying to create my own Timer that allows me to show elapsed time

I create the follow class but it returns thread problem where I assign the countdown value in a label (or any component) of the form,

How can i solve?

How to test:
Create a form as Form1
add the TimerR as TimerR1
set TimerR1.enable to true
set TimerR1.ActiveCountDown to False
At the event TimerR1_CountDown set the Form1 Text to e.CountDownSeconds

The Class


Public Class TimerR
Inherits System.Windows.Forms.Timer

Dim WithEvents aTimer As New System.Timers.Timer

Public Class EventArgs_CountDown
Inherits EventArgs

Public TimerIsActive As Boolean
Public TimerInterval As Integer
Public ElapsedSeconds As Integer
Public ElapsedMilliSeconds As Integer
Public CountDownSeconds As Integer

Public ErrorMessage As String

End Class
Public Shared Event CountDown(sender As Object, e As EventArgs_CountDown)

Public Sub New()
Me.Interval = 10000
End Sub


Private _ActiveCountDown As Boolean = False
Public Property ActiveCountDown As Boolean
Get
Return _ActiveCountDown
End Get
Set(ByVal Value As Boolean)

_ActiveCountDown = Value
aTimer.AutoReset = True
aTimer.Interval = 1000 '1 second
If _ActiveCountDown Then
AddHandler aTimer.Elapsed, AddressOf InternalTick
aTimer.Start()
Else
RemoveHandler aTimer.Elapsed, AddressOf InternalTick
aTimer.Stop()
End If

End Set
End Property

Friend Sub InternalTick(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)

Static Elapsed As Long = 0

Dim e1 As New EventArgs_CountDown

e1.TimerIsActive = Me.Enabled

Try

If e1.TimerIsActive = False Then
Elapsed = 0
e1.ElapsedSeconds = 0
e1.ElapsedMilliSeconds = 0
e1.CountDownSeconds = 0
Else
Elapsed += aTimer.Interval
e1.ElapsedSeconds = Elapsed / 1000
e1.ElapsedMilliSeconds = Elapsed
e1.CountDownSeconds = Int((Me.Interval / 1000) - e1.ElapsedSeconds)
End If

e1.TimerInterval = Me.Interval
e1.ErrorMessage = ""

Catch ex As Exception
e1.ErrorMessage = ex.Message

End Try

RaiseEvent CountDown(sender, e1)

End Sub



End Class
 
Resolved!
For now I am not able to detect automatically the form where is monted the control, so if you use these class, at form load you must whrite:

TimerR1.FormToFill = Me

Now the class of the component:

Public Class TimerR
Inherits System.Windows.Forms.Timer

Public FormToFill As New Form
Public Class EventArgs_CountDown
Inherits EventArgs

Public TimerIsActive As Boolean
Public TimerInterval As Integer
Public ElapsedSeconds As Integer
Public ElapsedMilliSeconds As Integer
Public CountDownSeconds As Integer
Public CountDownMilliSeconds As Integer

Public ErrorMessage As String

End Class
Public Shared Event CountDown(sender As Object, e As EventArgs_CountDown)

Dim elapTimer As New Threading.Timer(AddressOf TickInterno, Nothing, 250, 250)
Public stpw As New Stopwatch '= Stopwatch.StartNew



Public Sub New()

FormToFill = Nothing
stpw.Restart()

End Sub

Private Sub TickBase(sender As Object, e As EventArgs) Handles Me.Tick
stpw.Restart()
End Sub


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

Public Overloads Sub [Start]()
If Not Me.Enabled Then
stpw.Restart()
Me.Enabled = True
End If
End Sub

Private Sub TickInterno(state As Object)

Static old As String = ""

If stpw.IsRunning Then

If IsNothing(FormToFill) Then
Exit Sub
End If

Dim e As New EventArgs_CountDown

e.TimerIsActive = Me.Enabled

Try

If e.TimerIsActive = False Then

e.ElapsedSeconds = 0
e.ElapsedMilliSeconds = 0
e.CountDownSeconds = 0
e.CountDownMilliSeconds = 0
Else

e.ElapsedSeconds = stpw.ElapsedMilliseconds / 1000
e.ElapsedMilliSeconds = stpw.ElapsedMilliseconds
e.CountDownMilliSeconds = Me.Interval - e.ElapsedSeconds

If e.CountDownMilliSeconds < 0 Then
e.CountDownMilliSeconds = 0
End If

e.CountDownSeconds = Int(e.CountDownMilliSeconds / 1000)
End If

e.TimerInterval = Me.Interval
e.ErrorMessage = ""

Catch ex As Exception
e.ErrorMessage = ex.Message

End Try


If old <> e.TimerIsActive.ToString & e.CountDownSeconds.ToString & e.ErrorMessage Then
old = e.TimerIsActive.ToString & e.CountDownSeconds.ToString & e.ErrorMessage

FormToFill.Invoke(Sub()
RaiseEvent CountDown(Me, e)
End Sub)
End If

Else
stpw.Restart()
End If

End Sub

End Class
 
There was a little refuse....
now works fine

I hope someome explan me how to use something like .FindForm in this contraol


Public Class TimerR
Inherits System.Windows.Forms.Timer

Public FormToFill As New Object
Public Class EventArgs_CountDown
Inherits EventArgs

Public TimerIsActive As Boolean
Public TimerInterval As Integer
Public ElapsedSeconds As Integer
Public ElapsedMilliSeconds As Integer
Public CountDownSeconds As Integer
Public CountDownMilliSeconds As Integer

Public ErrorMessage As String

End Class
Public Shared Event CountDown(sender As Object, e As EventArgs_CountDown)

Dim elapTimer As New Threading.Timer(AddressOf TickInterno, Nothing, 250, 250)
Dim stpw As New Stopwatch



Public Sub New()
' Me.Interval = 1000
FormToFill = Nothing

stpw.Restart()

End Sub

Private Sub TickBase(sender As Object, e As EventArgs) Handles Me.Tick
stpw.Restart()
End Sub


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

Public Overloads Sub [Start]()
If Not Me.Enabled Then
stpw.Restart()
Me.Enabled = True
End If
End Sub

Private Sub TickInterno(state As Object)

Static old As String = ""

If stpw.IsRunning Then

If IsNothing(FormToFill) Then
Exit Sub
End If

Dim e As New EventArgs_CountDown

e.TimerIsActive = Me.Enabled

Try

If e.TimerIsActive = False Then

e.ElapsedSeconds = 0
e.ElapsedMilliSeconds = 0
e.CountDownSeconds = 0
e.CountDownMilliSeconds = 0
Else

e.ElapsedSeconds = stpw.ElapsedMilliseconds / 1000
e.ElapsedMilliSeconds = stpw.ElapsedMilliseconds
e.CountDownMilliSeconds = Me.Interval - stpw.ElapsedMilliseconds

If e.CountDownMilliSeconds < 0 Then
e.CountDownMilliSeconds = 0
End If

e.CountDownSeconds = Int(e.CountDownMilliSeconds / 1000)
End If

e.TimerInterval = Me.Interval
e.ErrorMessage = ""

Catch ex As Exception
e.ErrorMessage = ex.Message

End Try


If old <> e.TimerIsActive.ToString & e.CountDownSeconds.ToString & e.ErrorMessage Then
old = e.TimerIsActive.ToString & e.CountDownSeconds.ToString & e.ErrorMessage



FormToFill.Invoke(Sub()
RaiseEvent CountDown(Me, e)
End Sub)
End If

Else
stpw.Restart()
End If
End Sub
End Class
 
Please, for future, investigate what these buttons do, and use them:

1693990657702.png
 
Back
Top