 |
|
| .NET DotNet Forum Index » General Discussion » Are Threading.Timers Supposed to be Accurate?... |
|
Page 1 of 1 |
|
| Author |
Message |
| Charles... |
Posted: Mon Oct 26, 2009 5:45 pm |
|
|
|
Guest
|
Perhaps I have misunderstood how these things work. I have a Threading.Timer
object set to go off every 10 seconds. The timer callback sends some data
out on a TCP socket and checks for a reply. It then terminates. It will only
wait for a maximum of 5 seconds, but occasionally it will timeout and exit.
If the first callback occurs at time t and takes 5 seconds to complete, I am
expecting the next callback to occur at t+10. That's correct, isn't it?
What I am finding is that sometimes a callback doesn't occur for as much as
22 seconds after the previous one. What could cause this?
Would a System.Timers.Timer be any better?
TIA
Charles |
|
|
| Back to top |
|
|
|
| Michael D. Ober... |
Posted: Mon Oct 26, 2009 7:36 pm |
|
|
|
Guest
|
"Charles" <blank at (no spam) nowhere.com> wrote in message
news:e2gveZpVKHA.1280 at (no spam) TK2MSFTNGP04.phx.gbl...
Quote: Perhaps I have misunderstood how these things work. I have a
Threading.Timer object set to go off every 10 seconds. The timer callback
sends some data out on a TCP socket and checks for a reply. It then
terminates. It will only wait for a maximum of 5 seconds, but occasionally
it will timeout and exit.
If the first callback occurs at time t and takes 5 seconds to complete, I
am expecting the next callback to occur at t+10. That's correct, isn't it?
What I am finding is that sometimes a callback doesn't occur for as much
as 22 seconds after the previous one. What could cause this?
Would a System.Timers.Timer be any better?
TIA
Charles
I'm not sure how dotnet handles timers, but in the underlying Windows API,
your first scenario simply can't happen (t+5) for a 10 second timer. Your
second scenario can happen in the rare situation where your system is
extremely busy and sluggish. Basically, the Windows Timer (WM_TIMER)
messages are the second lowest priority messages in the system - only the
WM_PAINT message that generates the OnPaint() event is lower and only occurs
if there are no other messages waiting to be processed.
Please post your timer creation code so we can better help.
Mike Ober. |
|
|
| Back to top |
|
|
|
| Charles... |
Posted: Mon Oct 26, 2009 8:33 pm |
|
|
|
Guest
|
Hi Michael
Thanks for the reply.
Quote: your first scenario simply can't happen (t+5) for a 10 second timer. Your
I meant that the callback takes 5 seconds to do its work, but below I have
seen teh callback report 5 seconds.
Here's the code
' Create timer
m_Timer = New Threading.Timer(AddressOf TimerCallback, New TimerState,
10000, 10000)
And the TimerCallback function is
Private Sub PollCallback(ByVal state As Object)
SyncLock Me
Try
Dim TimeNow As DateTime = Now
ts = DirectCast(state, TimerState)
If Not ts.FirstTime Then
Dim ElapsedSeconds As Long =
DateDiff(DateInterval.Second, ts.LastCalled, TimeNow)
If ElapsedSeconds < 9 Then
' Called too quickly
OnTimerError(String.Format("Timer Request queued too
quickly, in {0} seconds", ElapsedSeconds))
ElseIf ElapsedSeconds > 11 Then
' Called too slowly
OnTimerError(String.Format("Timer Request queued too
slowly, in {0} seconds", ElapsedSeconds))
End If
End If
ts.LastCalled = TimeNow ' assignment clears FirstTime
flag
' Do stuff that takes 1 to 5 seconds
End SyncLock
End Sub
Sometimes it reports 5 seconds, sometimes 14, sometimes 25. Mostly it
reports nothing.
There are other things going on in the app, but mostly just waiting on wait
handles for things to be signalled, like messages coming in. CPU never gets
abovre a few percent for the whole machine, running Windows Server 2003.
Charles
"Michael D. Ober" <obermd. at (no spam) .alum.mit.edu.nospam.> wrote in message
news:qs6dnUhCqKw003vXnZ2dnUVZ_uidnZ2d at (no spam) earthlink.com...
Quote: "Charles" <blank at (no spam) nowhere.com> wrote in message
news:e2gveZpVKHA.1280 at (no spam) TK2MSFTNGP04.phx.gbl...
Perhaps I have misunderstood how these things work. I have a
Threading.Timer object set to go off every 10 seconds. The timer callback
sends some data out on a TCP socket and checks for a reply. It then
terminates. It will only wait for a maximum of 5 seconds, but
occasionally it will timeout and exit.
If the first callback occurs at time t and takes 5 seconds to complete, I
am expecting the next callback to occur at t+10. That's correct, isn't
it?
What I am finding is that sometimes a callback doesn't occur for as much
as 22 seconds after the previous one. What could cause this?
Would a System.Timers.Timer be any better?
TIA
Charles
I'm not sure how dotnet handles timers, but in the underlying Windows API,
your first scenario simply can't happen (t+5) for a 10 second timer. Your
second scenario can happen in the rare situation where your system is
extremely busy and sluggish. Basically, the Windows Timer (WM_TIMER)
messages are the second lowest priority messages in the system - only the
WM_PAINT message that generates the OnPaint() event is lower and only
occurs if there are no other messages waiting to be processed.
Please post your timer creation code so we can better help.
Mike Ober.
|
|
|
| Back to top |
|
|
|
| Family Tree Mike... |
Posted: Tue Oct 27, 2009 5:33 am |
|
|
|
Guest
|
"Charles" wrote:
Quote:
Sometimes it reports 5 seconds, sometimes 14, sometimes 25. Mostly it
reports nothing.
There are other things going on in the app, but mostly just waiting on wait
handles for things to be signalled, like messages coming in. CPU never gets
abovre a few percent for the whole machine, running Windows Server 2003.
Charles
It must be somewhere else in your code. The following code "never" (running
for several minutes) shows the issue you describe, and is based off the code
provided:
Module Module1
Public Class TimerState
Public LastCalled As DateTime
Public FirstTime As Boolean
Sub New()
FirstTime = True
End Sub
End Class
Public Class TimerContainer
Private m_Timer As Threading.Timer
Private Sub PollCallback(ByVal state As Object)
SyncLock Me
Try
Console.WriteLine("HERE")
Dim TimeNow As DateTime = Now
Dim ts As TimerState = DirectCast(state, TimerState)
If Not ts.FirstTime Then
Dim ElapsedSeconds As Long = DateDiff(DateInterval.Second,
ts.LastCalled, TimeNow)
If ElapsedSeconds < 9 Then
' Called too quickly
OnTimerError(String.Format("Timer Request queued too quickly, in {0}
seconds", ElapsedSeconds))
ElseIf ElapsedSeconds > 11 Then
' Called too slowly
OnTimerError(String.Format("Timer Request queued too slowly, in {0}
seconds", ElapsedSeconds))
End If
End If
ts.LastCalled = TimeNow ' assignment clears FirstTime flag()
' Do stuff that takes 1 to 5 seconds
LongProcedure()
Catch
End Try
End SyncLock
End Sub
Sub LongProcedure()
Dim sw As New Stopwatch
sw.Start()
Dim r As New Random
Dim n As Integer = 40000000
Dim numbers As New List(Of Integer)
For i As Integer = 1 To n
numbers.Add(r.Next(0, n))
Next
numbers.Sort()
Console.WriteLine(sw.ElapsedMilliseconds)
End Sub
Sub OnTimerError(ByVal msg As String)
Console.WriteLine(msg)
End Sub
Public Sub New()
m_Timer = New Threading.Timer(AddressOf PollCallback, New TimerState,
10000, 10000)
End Sub
End Class
Sub Main()
Dim tc As New TimerContainer()
Console.WriteLine("waiting...")
Console.ReadKey(True)
End Sub
End Module
Mike |
|
|
| Back to top |
|
|
|
| Michael D. Ober... |
Posted: Tue Oct 27, 2009 5:56 am |
|
|
|
Guest
|
"Charles" <blank at (no spam) nowhere.com> wrote in message
news:unkWY3qVKHA.5368 at (no spam) TK2MSFTNGP02.phx.gbl...
Quote: Hi Michael
Thanks for the reply.
your first scenario simply can't happen (t+5) for a 10 second timer.
Your
I meant that the callback takes 5 seconds to do its work, but below I have
seen teh callback report 5 seconds.
Here's the code
' Create timer
m_Timer = New Threading.Timer(AddressOf TimerCallback, New TimerState,
10000, 10000)
And the TimerCallback function is
Private Sub PollCallback(ByVal state As Object)
SyncLock Me
Try
Dim TimeNow As DateTime = Now
ts = DirectCast(state, TimerState)
If Not ts.FirstTime Then
Dim ElapsedSeconds As Long =
DateDiff(DateInterval.Second, ts.LastCalled, TimeNow)
If ElapsedSeconds < 9 Then
' Called too quickly
OnTimerError(String.Format("Timer Request queued
too quickly, in {0} seconds", ElapsedSeconds))
ElseIf ElapsedSeconds > 11 Then
' Called too slowly
OnTimerError(String.Format("Timer Request queued
too slowly, in {0} seconds", ElapsedSeconds))
End If
End If
ts.LastCalled = TimeNow ' assignment clears FirstTime
flag
' Do stuff that takes 1 to 5 seconds
End SyncLock
End Sub
Sometimes it reports 5 seconds, sometimes 14, sometimes 25. Mostly it
reports nothing.
There are other things going on in the app, but mostly just waiting on
wait handles for things to be signalled, like messages coming in. CPU
never gets abovre a few percent for the whole machine, running Windows
Server 2003.
Charles
"Michael D. Ober" <obermd. at (no spam) .alum.mit.edu.nospam.> wrote in message
news:qs6dnUhCqKw003vXnZ2dnUVZ_uidnZ2d at (no spam) earthlink.com...
"Charles" <blank at (no spam) nowhere.com> wrote in message
news:e2gveZpVKHA.1280 at (no spam) TK2MSFTNGP04.phx.gbl...
Perhaps I have misunderstood how these things work. I have a
Threading.Timer object set to go off every 10 seconds. The timer
callback sends some data out on a TCP socket and checks for a reply. It
then terminates. It will only wait for a maximum of 5 seconds, but
occasionally it will timeout and exit.
If the first callback occurs at time t and takes 5 seconds to complete,
I am expecting the next callback to occur at t+10. That's correct, isn't
it?
What I am finding is that sometimes a callback doesn't occur for as much
as 22 seconds after the previous one. What could cause this?
Would a System.Timers.Timer be any better?
TIA
Charles
I'm not sure how dotnet handles timers, but in the underlying Windows
API, your first scenario simply can't happen (t+5) for a 10 second timer.
Your second scenario can happen in the rare situation where your system
is extremely busy and sluggish. Basically, the Windows Timer (WM_TIMER)
messages are the second lowest priority messages in the system - only the
WM_PAINT message that generates the OnPaint() event is lower and only
occurs if there are no other messages waiting to be processed.
Please post your timer creation code so we can better help.
Mike Ober.
Put the statement "debug.write(now.tostring()) as your very first statement
inside PollCallback. What are the timing intervals. If they vary from 10
seconds, then something else is occurring. Start by commenting out the rest
of PollCallback() and add one statement block at a time. Also, SyncLock Me
is a bad idea as this locks the entire object and can cause strange
interactions with event handlers.
Mike. |
|
|
| Back to top |
|
|
|
| Charles... |
Posted: Tue Oct 27, 2009 9:48 am |
|
|
|
Guest
|
Hi Mike
I think I have found the cause of the problem: the server is running Backup
Exec, and it had amassed itself a virtual memory size of 22 Gb, with a
working set of 14 Gb, on a machine with 16 Gb physical memory. I can only
assume that it was causing things to freeze for many seconds and that pushed
the timer over the edge.
I have restarted the BE services and its footprint is down to 0.8 Gb and a
working set of just 0.4 Gb. Everything seems to be back to normal again,
touch wood.
Cheers
Charles
"Family Tree Mike" <FamilyTreeMike at (no spam) discussions.microsoft.com> wrote in
message news:A03C326D-0A0A-4233-8DB2-0FBDBEDDEB68 at (no spam) microsoft.com...
Quote:
"Charles" wrote:
Sometimes it reports 5 seconds, sometimes 14, sometimes 25. Mostly it
reports nothing.
There are other things going on in the app, but mostly just waiting on
wait
handles for things to be signalled, like messages coming in. CPU never
gets
abovre a few percent for the whole machine, running Windows Server 2003.
Charles
It must be somewhere else in your code. The following code "never"
(running
for several minutes) shows the issue you describe, and is based off the
code
provided:
Module Module1
Public Class TimerState
Public LastCalled As DateTime
Public FirstTime As Boolean
Sub New()
FirstTime = True
End Sub
End Class
Public Class TimerContainer
Private m_Timer As Threading.Timer
Private Sub PollCallback(ByVal state As Object)
SyncLock Me
Try
Console.WriteLine("HERE")
Dim TimeNow As DateTime = Now
Dim ts As TimerState = DirectCast(state, TimerState)
If Not ts.FirstTime Then
Dim ElapsedSeconds As Long = DateDiff(DateInterval.Second,
ts.LastCalled, TimeNow)
If ElapsedSeconds < 9 Then
' Called too quickly
OnTimerError(String.Format("Timer Request queued too quickly, in {0}
seconds", ElapsedSeconds))
ElseIf ElapsedSeconds > 11 Then
' Called too slowly
OnTimerError(String.Format("Timer Request queued too slowly, in {0}
seconds", ElapsedSeconds))
End If
End If
ts.LastCalled = TimeNow ' assignment clears FirstTime flag()
' Do stuff that takes 1 to 5 seconds
LongProcedure()
Catch
End Try
End SyncLock
End Sub
Sub LongProcedure()
Dim sw As New Stopwatch
sw.Start()
Dim r As New Random
Dim n As Integer = 40000000
Dim numbers As New List(Of Integer)
For i As Integer = 1 To n
numbers.Add(r.Next(0, n))
Next
numbers.Sort()
Console.WriteLine(sw.ElapsedMilliseconds)
End Sub
Sub OnTimerError(ByVal msg As String)
Console.WriteLine(msg)
End Sub
Public Sub New()
m_Timer = New Threading.Timer(AddressOf PollCallback, New TimerState,
10000, 10000)
End Sub
End Class
Sub Main()
Dim tc As New TimerContainer()
Console.WriteLine("waiting...")
Console.ReadKey(True)
End Sub
End Module
Mike |
|
|
| Back to top |
|
|
|
| Charles... |
Posted: Tue Oct 27, 2009 9:50 am |
|
|
|
Guest
|
Hi Mike
You might see from my reply to the other Mike that I think I have found the
problem. I didn't have much respect for BE before I started, and now it has
plummeted!
Anyway, all good now, I think, and I will change the SyncLock statement as
well.
Cheers
Charles
"Michael D. Ober" <obermd. at (no spam) .alum.mit.edu.nospam.> wrote in message
news:Fb2dnR_0pJ9xQnvXnZ2dnUVZ_uydnZ2d at (no spam) earthlink.com...
Quote: "Charles" <blank at (no spam) nowhere.com> wrote in message
news:unkWY3qVKHA.5368 at (no spam) TK2MSFTNGP02.phx.gbl...
Hi Michael
Thanks for the reply.
your first scenario simply can't happen (t+5) for a 10 second timer.
Your
I meant that the callback takes 5 seconds to do its work, but below I
have seen teh callback report 5 seconds.
Here's the code
' Create timer
m_Timer = New Threading.Timer(AddressOf TimerCallback, New TimerState,
10000, 10000)
And the TimerCallback function is
Private Sub PollCallback(ByVal state As Object)
SyncLock Me
Try
Dim TimeNow As DateTime = Now
ts = DirectCast(state, TimerState)
If Not ts.FirstTime Then
Dim ElapsedSeconds As Long =
DateDiff(DateInterval.Second, ts.LastCalled, TimeNow)
If ElapsedSeconds < 9 Then
' Called too quickly
OnTimerError(String.Format("Timer Request queued
too quickly, in {0} seconds", ElapsedSeconds))
ElseIf ElapsedSeconds > 11 Then
' Called too slowly
OnTimerError(String.Format("Timer Request queued
too slowly, in {0} seconds", ElapsedSeconds))
End If
End If
ts.LastCalled = TimeNow ' assignment clears FirstTime
flag
' Do stuff that takes 1 to 5 seconds
End SyncLock
End Sub
Sometimes it reports 5 seconds, sometimes 14, sometimes 25. Mostly it
reports nothing.
There are other things going on in the app, but mostly just waiting on
wait handles for things to be signalled, like messages coming in. CPU
never gets abovre a few percent for the whole machine, running Windows
Server 2003.
Charles
"Michael D. Ober" <obermd. at (no spam) .alum.mit.edu.nospam.> wrote in message
news:qs6dnUhCqKw003vXnZ2dnUVZ_uidnZ2d at (no spam) earthlink.com...
"Charles" <blank at (no spam) nowhere.com> wrote in message
news:e2gveZpVKHA.1280 at (no spam) TK2MSFTNGP04.phx.gbl...
Perhaps I have misunderstood how these things work. I have a
Threading.Timer object set to go off every 10 seconds. The timer
callback sends some data out on a TCP socket and checks for a reply. It
then terminates. It will only wait for a maximum of 5 seconds, but
occasionally it will timeout and exit.
If the first callback occurs at time t and takes 5 seconds to complete,
I am expecting the next callback to occur at t+10. That's correct,
isn't it?
What I am finding is that sometimes a callback doesn't occur for as
much as 22 seconds after the previous one. What could cause this?
Would a System.Timers.Timer be any better?
TIA
Charles
I'm not sure how dotnet handles timers, but in the underlying Windows
API, your first scenario simply can't happen (t+5) for a 10 second
timer. Your second scenario can happen in the rare situation where your
system is extremely busy and sluggish. Basically, the Windows Timer
(WM_TIMER) messages are the second lowest priority messages in the
system - only the WM_PAINT message that generates the OnPaint() event is
lower and only occurs if there are no other messages waiting to be
processed.
Please post your timer creation code so we can better help.
Mike Ober.
Put the statement "debug.write(now.tostring()) as your very first
statement inside PollCallback. What are the timing intervals. If they
vary from 10 seconds, then something else is occurring. Start by
commenting out the rest of PollCallback() and add one statement block at a
time. Also, SyncLock Me is a bad idea as this locks the entire object and
can cause strange interactions with event handlers.
Mike.
|
|
|
| Back to top |
|
|
|
| Michael D. Ober... |
Posted: Tue Oct 27, 2009 6:43 pm |
|
|
|
Guest
|
Charles,
I'm glad you found the problem. Heavy system paging (thrashing in your
case) will definitely interfere with the WM_TIMER messages.
Mike.
"Charles" <blank at (no spam) nowhere.com> wrote in message
news:uxT930xVKHA.5208 at (no spam) TK2MSFTNGP05.phx.gbl...
Quote: Hi Mike
You might see from my reply to the other Mike that I think I have found
the problem. I didn't have much respect for BE before I started, and now
it has plummeted!
Anyway, all good now, I think, and I will change the SyncLock statement as
well.
Cheers
Charles
"Michael D. Ober" <obermd. at (no spam) .alum.mit.edu.nospam.> wrote in message
news:Fb2dnR_0pJ9xQnvXnZ2dnUVZ_uydnZ2d at (no spam) earthlink.com...
"Charles" <blank at (no spam) nowhere.com> wrote in message
news:unkWY3qVKHA.5368 at (no spam) TK2MSFTNGP02.phx.gbl...
Hi Michael
Thanks for the reply.
your first scenario simply can't happen (t+5) for a 10 second timer.
Your
I meant that the callback takes 5 seconds to do its work, but below I
have seen teh callback report 5 seconds.
Here's the code
' Create timer
m_Timer = New Threading.Timer(AddressOf TimerCallback, New
TimerState, 10000, 10000)
And the TimerCallback function is
Private Sub PollCallback(ByVal state As Object)
SyncLock Me
Try
Dim TimeNow As DateTime = Now
ts = DirectCast(state, TimerState)
If Not ts.FirstTime Then
Dim ElapsedSeconds As Long =
DateDiff(DateInterval.Second, ts.LastCalled, TimeNow)
If ElapsedSeconds < 9 Then
' Called too quickly
OnTimerError(String.Format("Timer Request queued
too quickly, in {0} seconds", ElapsedSeconds))
ElseIf ElapsedSeconds > 11 Then
' Called too slowly
OnTimerError(String.Format("Timer Request queued
too slowly, in {0} seconds", ElapsedSeconds))
End If
End If
ts.LastCalled = TimeNow ' assignment clears FirstTime
flag
' Do stuff that takes 1 to 5 seconds
End SyncLock
End Sub
Sometimes it reports 5 seconds, sometimes 14, sometimes 25. Mostly it
reports nothing.
There are other things going on in the app, but mostly just waiting on
wait handles for things to be signalled, like messages coming in. CPU
never gets abovre a few percent for the whole machine, running Windows
Server 2003.
Charles
"Michael D. Ober" <obermd. at (no spam) .alum.mit.edu.nospam.> wrote in message
news:qs6dnUhCqKw003vXnZ2dnUVZ_uidnZ2d at (no spam) earthlink.com...
"Charles" <blank at (no spam) nowhere.com> wrote in message
news:e2gveZpVKHA.1280 at (no spam) TK2MSFTNGP04.phx.gbl...
Perhaps I have misunderstood how these things work. I have a
Threading.Timer object set to go off every 10 seconds. The timer
callback sends some data out on a TCP socket and checks for a reply.
It then terminates. It will only wait for a maximum of 5 seconds, but
occasionally it will timeout and exit.
If the first callback occurs at time t and takes 5 seconds to
complete, I am expecting the next callback to occur at t+10. That's
correct, isn't it?
What I am finding is that sometimes a callback doesn't occur for as
much as 22 seconds after the previous one. What could cause this?
Would a System.Timers.Timer be any better?
TIA
Charles
I'm not sure how dotnet handles timers, but in the underlying Windows
API, your first scenario simply can't happen (t+5) for a 10 second
timer. Your second scenario can happen in the rare situation where your
system is extremely busy and sluggish. Basically, the Windows Timer
(WM_TIMER) messages are the second lowest priority messages in the
system - only the WM_PAINT message that generates the OnPaint() event
is lower and only occurs if there are no other messages waiting to be
processed.
Please post your timer creation code so we can better help.
Mike Ober.
Put the statement "debug.write(now.tostring()) as your very first
statement inside PollCallback. What are the timing intervals. If they
vary from 10 seconds, then something else is occurring. Start by
commenting out the rest of PollCallback() and add one statement block at
a time. Also, SyncLock Me is a bad idea as this locks the entire object
and can cause strange interactions with event handlers.
Mike.
|
|
|
| Back to top |
|
|
|
|
|
All times are GMT - 5 Hours
The time now is Tue Dec 15, 2009 5:01 am
|
|