Discussion:
SYSTEM.TIMERS.TIMER pausieren lassen
(zu alt für eine Antwort)
Michael Kolowicz
2009-09-16 13:01:19 UTC
Permalink
Hallo,

welche Möglichkeit habe ich um in VB.NET eine Timer zu pausieren.

Ich habe zwei Timer in einer Anwendung laufen. Wenn der erste seinen
Tick ausführt, soll der zweite angehalten werden, bis der erste fertig
ist. dann soll der zweite weiterlaufen (Restzeit) und nicht neu anfangen
zu zählen

Leider habe ich kein .pause gefunden.

Ist der Weg, über das speichern des aktuellen Wetes in eine variabel und
dann erneutes starten mit diesem Wert der korrekte Weg oder gibt es
einen einfacheren Weg dazu

mfg
Michael
Peter Fleischer
2009-09-16 13:37:45 UTC
Permalink
Post by Michael Kolowicz
welche Möglichkeit habe ich um in VB.NET eine Timer zu pausieren.
Ich habe zwei Timer in einer Anwendung laufen. Wenn der erste seinen
Tick ausführt, soll der zweite angehalten werden, bis der erste fertig
ist. dann soll der zweite weiterlaufen (Restzeit) und nicht neu anfangen
zu zählen
Leider habe ich kein .pause gefunden.
Ist der Weg, über das speichern des aktuellen Wetes in eine variabel und
dann erneutes starten mit diesem Wert der korrekte Weg oder gibt es
einen einfacheren Weg dazu
Hi Michael,
da der Zeitgeber asynchron arbeitet, wirst du auch keine Möglichkeit haben,
den Zeitgeber anzuhalten.

Wenn alles in einem thread läuft, dann solltest du für Zeitintervalle, die
aus Teilzeitsummen eine entsprechende Routine bauen, die beispielsweise eine
Queue für die Teilzeiten nutzt.

Wenn du in unterschiedlichen threads arbeitest, solltest du mal genauer das
zu erreichende Ziel beschreiben.
--
Viele Grüsse
Peter
Michael Kolowicz
2009-09-16 13:50:33 UTC
Permalink
solltest du mal genauer das zu erreichende Ziel beschreiben.
OK, das mach ich mal:

Ich habe eine Anwendung. Diese soll verschiedene Aufgaben zu
uunterschiedlichen Zeitpunkten ausführen.

Ich verwende daher 3 Timer (A, B, C)

A = 2 Minuten; B = 5 Minuten; C= 120 Minuten

Wenn A das 5. mal startet, kommt es in Kollision mit B, der das 2. mal
startet

Ich wollte jetzt gerne A ausführen lassen, B und C anhalten, wenn A
fertig ist, B (jetzt noch 3 Minuten) und C (noch 118 Minuten)
weiterlaufen lassen

Ist das so verständlich?

Habe es auch schon über Process.WaitToExit verscuht, aber da der Process
mit em Timern als "Normaler" Benutzer laäuft und die Aufgaben als
"Admin" laufen, kann ich dass leider nicht nutzen (Zugriffs-Fehler)

mfg
Michael
Peter Fleischer
2009-09-16 17:53:37 UTC
Permalink
Post by Michael Kolowicz
solltest du mal genauer das zu erreichende Ziel beschreiben.
Hi Michael,
durchdacht ist das Konzept aber immer noch nicht.
Post by Michael Kolowicz
Ich habe eine Anwendung. Diese soll verschiedene Aufgaben zu
uunterschiedlichen Zeitpunkten ausführen.
Ich verwende daher 3 Timer (A, B, C)
Warum 3 Timer? Erzeugen diese Timer einen einmaligen Intervall oder arbeiten
sie zyklisch?
Post by Michael Kolowicz
A = 2 Minuten; B = 5 Minuten; C= 120 Minuten
Wenn A das 5. mal startet, kommt es in Kollision mit B, der das 2. mal
startet
Ich wollte jetzt gerne A ausführen lassen, B und C anhalten, wenn A
fertig ist, B (jetzt noch 3 Minuten) und C (noch 118 Minuten)
weiterlaufen lassen
Wird beim Anhalten die Wartezeit zur absoluten Zeit bis zum nächsten Zyklus
dazuaddiert oder geht die verloren?
Post by Michael Kolowicz
Ist das so verständlich?
Nein, s. oben.
--
Viele Grüsse
Peter
Michael Kolowicz
2009-09-16 19:29:39 UTC
Permalink
Post by Peter Fleischer
Warum 3 Timer? Erzeugen diese Timer einen einmaligen Intervall oder arbeiten
sie zyklisch?
Diese Timer enden dann. Werden aber nach dem abarbeiten der Aufgabe
wieder vom Programm gestartet. Damit sich die Aufgabe nicht selbtst ins
Gehege kommt.
Post by Peter Fleischer
Post by Michael Kolowicz
A = 2 Minuten; B = 5 Minuten; C= 120 Minuten
Wenn A das 5. mal startet, kommt es in Kollision mit B, der das 2. mal
startet
Ich wollte jetzt gerne A ausführen lassen, B und C anhalten, wenn A
fertig ist, B (jetzt noch 3 Minuten) und C (noch 118 Minuten)
weiterlaufen lassen
Wird beim Anhalten die Wartezeit zur absoluten Zeit bis zum nächsten Zyklus
dazuaddiert oder geht die verloren?
Die Wartezeit kann unberücksichtigt werden. Im Moment sieht es so aus:
Timer A läuft nach 2 Min. ab - die Aufgabe dauert 3 Minuten ( A ist
gestoppt) - A wird wieder gestartet
Post by Peter Fleischer
Post by Michael Kolowicz
Ist das so verständlich?
Nein, s. oben.
Peter Fleischer
2009-09-17 10:11:23 UTC
Permalink
Post by Michael Kolowicz
Post by Peter Fleischer
Warum 3 Timer? Erzeugen diese Timer einen einmaligen Intervall oder arbeiten
sie zyklisch?
Diese Timer enden dann. Werden aber nach dem abarbeiten der Aufgabe
wieder vom Programm gestartet. Damit sich die Aufgabe nicht selbtst ins
Gehege kommt.
Hi Michael,
hier mal eine Demo, in der der nächste Intervall erst am Ende der Methode
(SubA, SubB bzw. SubC) gestartet wird:

Option Infer On ' Only VB9
Option Strict On

Public Class Form1

Private Const interval_A As Integer = 300 ' Millseconds for TimerA
Private Const interval_B As Integer = 600 ' Millseconds for TimerB
Private Const interval_C As Integer = 1200 ' Millseconds for TimerC

Private WithEvents Timer1 As New Timer _
With {.Interval = interval_A, _
.Tag = New clsWorkItem With {.Method = AddressOf SubA, .ID =
"A"}}
Private WithEvents Timer2 As New Timer _
With {.Interval = interval_B, _
.Tag = New clsWorkItem With {.Method = AddressOf SubB, .ID =
"B"}}
Private WithEvents Timer3 As New Timer _
With {.Interval = interval_C, _
.Tag = New clsWorkItem With {.Method = AddressOf SubC, .ID =
"C"}}

Dim lb As New ListBox With {.Dock = DockStyle.Fill}
Dim WithEvents btn1 As New Button With {.Dock = DockStyle.Top, .Text =
"Start"}
Dim WithEvents btn2 As New Button With {.Dock = DockStyle.Top, .Text =
"Stopp"}

Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.Load
Me.Controls.AddRange(New Control() {lb, btn2, btn1})
End Sub

Private Sub Form1_FormClosing(ByVal sender As Object, _
ByVal e As
System.Windows.Forms.FormClosingEventArgs) _
Handles Me.FormClosing
btn2_Click(Nothing, Nothing)
End Sub

Private Sub btn1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles btn1.Click
' Timer starten
Timer1.Start()
Timer2.Start()
Timer3.Start()
End Sub

Private Sub btn2_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles btn2.Click
' Timer beenden
Timer1.Stop()
Timer2.Stop()
Timer3.Stop()
End Sub

Private workerQueue As New Queue(Of clsWorkItem)

Private Sub Timer_Tick(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Timer1.Tick, Timer2.Tick, Timer3.Tick
Dim t = CType(sender, Timer)
t.Stop()
SyncLock Me
workerQueue.Enqueue(CType(t.Tag, clsWorkItem))
If workerQueue.Count > 1 Then Exit Sub
End SyncLock
Do
Dim m = workerQueue.Peek
m.Method.Invoke()
SyncLock Me
workerQueue.Dequeue()
If workerQueue.Count = 0 Then Exit Do
End SyncLock
Loop
End Sub

Delegate Sub methodDelegate()

Private Sub SubA()
ShowMessage("Start A")
' Timer-Neustart
Timer1.Start()
ShowMessage("Ende A")
End Sub

Private Sub SubB()
ShowMessage("Start B")
' Timer-Neustart
Timer2.Start()
ShowMessage("Ende B")
End Sub

Private Sub SubC()
ShowMessage("Start C")
' Timer-Neustart
Timer3.Start()
ShowMessage("Ende C")
End Sub

Delegate Sub ShowMessagedeleg(ByVal s As String)
Private Sub ShowMessage(ByVal msg As String)
If lb.InvokeRequired Then
lb.Invoke(New ShowMessagedeleg(AddressOf ShowMessage), New Object()
{msg})
Else
lb.Items.Add(String.Format("{0:HH:mm:ss.fff} {1}", Now, msg))
lb.SelectedItem = lb.Items(lb.Items.Count - 1)
End If
End Sub

Friend Structure clsWorkItem
Friend Method As methodDelegate
Friend ID As String
End Structure

End Class
--
Viele Grüsse
Peter
Michael Kolowicz
2009-09-17 14:51:33 UTC
Permalink
Hallo Peter,

das Beispiel sieht gut aus. Ich werde es entsprechend anpassen.

Danke für deine Mühe

Michael

Martin H.
2009-09-16 21:46:51 UTC
Permalink
Hallo Michael,
Post by Michael Kolowicz
Ich wollte jetzt gerne A ausführen lassen, B und C anhalten, wenn A
fertig ist, B (jetzt noch 3 Minuten) und C (noch 118 Minuten)
weiterlaufen lassen
Ich habe ein kleines Beispielprojekt erstellt.
Erstelle eine leere Form und füge einen Timer (Timer1) und den
nachfolgenden Code ein. Pass bitte bei den Zeilenumbrüchen auf.

'Begin

#Region "Constants and Variables for the solution"

Private Const iDATE_INTERVAL_A = 6 'Seconds for TimerA
Private Const iDATE_INTERVAL_B = 30 'Seconds for TimerB
Private Const iDATE_INTERVAL_C = 42 'Seconds for TimerC

Private DateA As Date 'Date for next tick of TimerA
Private DateB As Date 'Date for next tick of TimerB
Private DateC As Date 'Date for next tick of TimerC

Private iCurrentSecondsA As Integer 'CurrentNumber of seconds of TimerA
Private iCurrentSecondsB As Integer 'CurrentNumber of seconds of TimerB
Private iCurrentSecondsC As Integer 'CurrentNumber of seconds of TimerC

#End Region

#Region "Variables for the demonstration"
Private PicA As PictureBox
Private PicB As PictureBox
Private PicC As PictureBox

Private GrpA As GroupBox
Private GrpB As GroupBox
Private GrpC As GroupBox

Private dStart As Date

Private Const sDATE_FORMAT = "dd. MMM yyyy HH:mm:ss"

#End Region

#Region "Subs and functions for the solution"
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Timer1.Tick
Time()
CheckTimes()
End Sub

Private Sub CheckTimes()
'This routine checks if one or more timers reached the time to fire.
Dim dNow As Date = Now

Dim iDiffA As Integer
Dim iDiffB As Integer
Dim iDiffC As Integer

'Check if it is 'Fire' time...
iDiffA = DateDiff(DateInterval.Second, dNow, DateA)
iDiffB = DateDiff(DateInterval.Second, dNow, DateB)
iDiffC = DateDiff(DateInterval.Second, dNow, DateC)

If iDiffA < 1 OrElse iDiffB < 1 OrElse iDiffC < 1 Then
Timer1.Enabled = False

If iDiffA < 1 Then
TickA()
End If

If iDiffB < 1 Then
TickB()
End If

If iDiffC < 1 Then
TickC()
End If

CalcRemainingSeconds(dNow)
CalcNewTimesAndEnableTimer()
End If

End Sub

Private Sub CalcRemainingSeconds(ByVal dNow As Date)
'This routine calculates the remaining seconds.
iCurrentSecondsA = CalcRemainingSeconds(dNow, DateA)
iCurrentSecondsB = CalcRemainingSeconds(dNow, DateB)
iCurrentSecondsC = CalcRemainingSeconds(dNow, DateC)
End Sub

Private Function CalcRemainingSeconds(ByVal dNow As Date, ByVal dTimer
As Date) As Integer
'This routine calculates the remaining seconds for a specific timer.
Dim retVal As Integer

retVal = DateDiff(DateInterval.Second, dNow, dTimer)

If retVal < 0 Then
retVal = 0
End If

Return retVal
End Function

Private Sub CalcNewTimesAndEnableTimer()
'This routine calculates the new time for the timers next fire events.
Dim dNow As Date = Now
DateA = CalcNewTime(dNow, iCurrentSecondsA, iDATE_INTERVAL_A)
DateB = CalcNewTime(dNow, iCurrentSecondsB, iDATE_INTERVAL_B)
DateC = CalcNewTime(dNow, iCurrentSecondsC, iDATE_INTERVAL_C)
Timer1.Enabled = True
End Sub

Private Function CalcNewTime(ByVal dNow As Date, ByVal iSecondsToGo As
Integer, ByVal iDefaultSeconds As Integer) As Date
'This routine calculates the new time for a specific timer.
Dim iSeconds As Integer
Dim retVal As Date

If iSecondsToGo < 1 Then
iSeconds = iDefaultSeconds
Else
iSeconds = iSecondsToGo
End If

retVal = DateAdd(DateInterval.Second, iSeconds, dNow)

Return retVal
End Function

Private Sub TickA()
'Fire event for TimerA.
DoSomething(PicA, GrpA) 'Here is your routine
End Sub

Private Sub TickB()
'Fire event for GimerB.
DoSomething(PicB, GrpB) 'Here is your routine
End Sub

Private Sub TickC()
'Fire event for TimerC.
DoSomething(PicC, GrpC) 'Here is your routine
End Sub
#End Region

#Region "Subs and functions for the demonstration"
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
dStart = Now
PrepareForm()
CalcNewTimesAndEnableTimer()
End Sub

Private Sub PrepareForm()
Me.Width = 630
Me.Height = 280
Time()
PrepareForm("A", 5, 5, PicA, GrpA)
PrepareForm("B", 210, 5, PicB, GrpB)
PrepareForm("C", 420, 5, PicC, GrpC)
End Sub

Private Sub Time()
Dim sStart As String = dStart.ToString(sDATE_FORMAT)
Dim sNow As String = Now.ToString(sDATE_FORMAT)
Me.Text = "Start: " & sStart & " / Now: " & sNow
End Sub

Private Sub PrepareForm(ByVal Name As String, ByVal iLeft As Integer,
ByVal iTop As Integer, ByRef PicBox As PictureBox, ByRef GrpBox As GroupBox)
Dim grp As New GroupBox
Dim Pic As New PictureBox

grp.Name = "Grp" & Name
grp.Width = 200
grp.Height = 220
grp.Text = "Timer " & Name
grp.Tag = grp.Text & ": ("
grp.Left = iLeft
grp.Top = iTop
grp.Visible = True

Pic.Name = "Pic" & Name
Pic.Width = 190
Pic.Height = 190
Pic.Left = 5
Pic.Top = 20
Pic.Visible = True

Me.Controls.Add(grp)
grp.Controls.Add(Pic)
PicBox = Pic
GrpBox = grp
End Sub

Private Sub DoSomething(ByRef Pic As PictureBox, ByRef grp As GroupBox)
Dim rn As New Random()

Dim r As Integer = rn.Next(0, 255)
Dim g As Integer = rn.Next(0, 255)
Dim b As Integer = rn.Next(0, 255)

Dim bmp As New Bitmap(Pic.Width, Pic.Height)
Dim clr As Color = Color.FromArgb(255, r, g, b)
Dim Pn As New Pen(clr)
Dim gr As Graphics = Graphics.FromImage(bmp)
Dim rct As New Rectangle(0, 0, bmp.Width, bmp.Height)
gr.DrawRectangle(Pn, rct)
gr.FillRectangle(Pn.Brush, rct)
gr.Dispose()
Pic.Image = Image.FromHbitmap(bmp.GetHbitmap)
grp.Text = grp.Tag & Now.ToString(sDATE_FORMAT) & ")"
End Sub
#End Region

'End

Beste Grüße,

Martin
Loading...