-------- start update and conclusion (30.08.2023) --------------
My timer code (postend below) run's without any problem in a windows forms client (vb.net). Starts to the "full minute" and then is fires any 10 seconds (the whole day).
The same code don't work in a windows service: don't fire any 10 seconds and delays a few seconds over a full day.
So... there are definitely differences, how a timer is handled in a windows client and in a windows service (I still don't know the reason).
I now have implemented the code from @dbasenett (see his answer to my question) in my windows service an let it run over the last night.
Result:
The timer starts to the full minute and then fires any 10 seconds over a full day (night).
NDD_Zeit ( 1 ) is the timestamp, when the data were stored on the SQL server and NDD_TradeTime_US ( 2 ) is the real trade time to the data, delivered over the json API from my broker.
In common, the data are stored/from exact any 10 seconds ( 3 )
Rarely ( 4 ) there is 1 second gap. But if there is a gap, it is only for one tic (with the timer it has started e.g. to 13, then become 24 and so on -> over ten seconds in full day).
So.. many thanks to @dbasnett for your posting, your support and for your patience;-)
I will set your answer as solution.
@any that need an exact timer in a windows service and have a problem with it: take the last version of the code in the answer of @dbasnett.
----------------------- end update und conclusion ----------------
I’m on the way to develop a robo-trader (automatic trading over an API to a broker).
The robo-trader (windows-) client access the real time data over an API every 10 second (query the data, buy and sell).
To be able to do tests (change code in the windows robo-trader and see the results in a fast and easy way), I also have developed a windows service that get the data every 10 seconds (like the client) and then stores the data on a SQL server, so that I am able to do simulations with the data on the SQL server (with history data).
The base problem was (is), that the data are not in sync.
E.g. the windows client get’s the data at 10:02:13 whereby the windows service get’s the (same) data at 10:02:19 what returns other data and can make a big difference depending on the implemented logic.
Therefore I wanted to sync the timer tics to the same second.
To reach the target, I have implemented two timers:
A one second timer, that starts the “real” 10 second timer (target: full minute).
A ten second timer, that do the real job.
So... first the on second timer is started and waits for a time with 50 seconds and then start the ten second timer.
Means the 10 second timer has to start on hh:mm:00 (on a full minute) and then have to fire every 10 seconds.
In the windows client this work like a charm: The timer is started on a full minute and the fires any 10 second (E.G. 10:02:00, 10:02:10, 10:02:10 and so on) for the whole trading day.
In the windows service, this (same code as in client) does – for whatever reason – don’t work (what I don’t understand):
The start of the ten second timer from the one second timer works correct (I can see this, as I write entries in the windows event log):
The ten second timer is started correct at 50 seconds (e.g. at 10:01:50).
But, it then fires the first time e.g. at 10:02:03, 10:02:13 and so on and later “loose” further time and change e.g. to 11:02:04 and so on.
So.. it seems as the timer in the windows client don’t work the same as the timer in the windows service, what I don’t understand (reason for this post).
Notes:
- The windows client and the windows service are running on the same machine (with the same clock, that is synced over the internet)
- I also have tried to run the windows service on a server -> same result
- The “work” in the ten second timer (query the data over the API and store the data on the SQL server) takes less than one second
So... the problem is, that the ten second timer in the windows service don’t fire after 10 seconds (he fires e.g. after 13 seconds the first time), after the (correct) start and later “lose” further time as longer as he is started, what I absolutely don’t understand (never seen such a behavior in a windows client).
I also have tried, to start the timer at 47 seconds (instead of 50 seconds) only to see, if it then starts on the full minute, what is not the case and confuse me in addition.
Code Snippets:
Timer definitions (in Class()
Public TimerDatenAbruf As New System.Timers.Timer() ' 10 second timer that does the work
Public TimerSekundenSync As New System.Timers.Timer() ' 1 Second timer that starts the 10 second timer
Timer setup (in OnStart()
TimerDatenAbruf.Interval = 10 * 1000 ' 10 Seconds for the 10 second timer
TimerSekundenSync.Interval = 1 * 1000 ' 1 Second for the 1 second timer
' Add of the handlers and start of the one second timer
AddHandler TimerSekundenSync.Elapsed, AddressOf SekundenTimerEvent
TimerSekundenSync.Enabled = True
TimerSekundenSync.Start()
AddHandler TimerDatenAbruf.Elapsed, AddressOf TimerDatenAbrufTimerEvent
Code to one second timer in SekundenTimerEvent()
Private Sub SekundenTimerEvent(source As Object, e As ElapsedEventArgs)
' Sync to the minute
Dim dtTimeStampAktuell As DateTime = System.DateTime.Now
Dim iSekunden As Integer = dtTimeStampAktuell.Second
If iSekunden = 50 Then
If Not TimerDatenAbruf.Enabled Then ' only start, if it don't already runs
TimerDatenAbruf.Start() ' start the ten second timer
TimerSekundenSync.Stop() ' stop the one second timer
End If
End If
End Sub
As I already wrote above, the ten second timer is started correct with the above code (at 50 seconds), but don't fire the firs time to the next minute and then loose further time as longer as it run's.
I hope somebody here can bring some light I the dark.
Thanks in advance for any hint.
Update (especially to @dbasnett):
I have implemented your code in the Windows-Client:
Result:
On the left side, you can see my ("old") code with the timers, on the right side you can see your code.
Both have started correct ( 1 ) and ( 2 ) and are showing the correct seconds after 12 Minutes ( 1.1 ) and ( 2.1 ) and also after 21 Minutes ( 1.2 ) and ( 2.2 )
As I worte, the "timer solution" in the windows client also run's correct after full 9 hours.
In the windows service the timer starts to drift after about 16 minutes...
So.. something is different regarding timers in an windows client and a windows service
I then have tried to implement your solution in the windows service (to give it a try in a windows service) and had several issues with it:
The data are queried over an async Json API with httpclient.
Therefore the call has to be awaited ( 1 ) and also the sub has to be async ( 2 )
As soon as I make the sub async, I'm not able to define the static variables ( 3 ) and ( 4 )
Further Me.BeginInvoke ( 5 ) is not available in a windows service (only in in a windows forms application).
So... if you are able to give me the correct code for a windows service, I will implement and test it...
Thanks!
Update #2 (especially to @dbasnett):
The data are queried in an async function: NasdaqDatenAbrufen() as task ( 1 )
I cannot await the task ( 2 )
I think of cause the "await t"
Without await, VS says, the task will not be awaited...
Thanks