Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Timer.Change() ever return false?

The .NET System.Threading Timer class has several overloaded Change() methods that return "true if the timer was successfully updated; otherwise, false."

Ref: http://msdn.microsoft.com/en-us/library/yz1c7148.aspx

Does this method ever actually return false? What would cause this to return false?

like image 292
noctonura Avatar asked Sep 25 '12 16:09

noctonura


People also ask

What is timer Change?

Changes the start time and the interval between method invocations for a timer, using 32-bit signed integers to measure time intervals. Change(Int64, Int64) Changes the start time and the interval between method invocations for a timer, using 64-bit signed integers to measure time intervals. Change(TimeSpan, TimeSpan)

How do you stop a timer thread?

Stopping Timer ThreadsInvoke cancel on the timer. You can do this from anywhere in the program, such as from a timer task's run method. Make the timer's thread a "daemon" by creating the timer like this: new Timer(true) . If the only threads left in the program are daemon threads, the program exits.


3 Answers

Joe Duffy (the development lead, architect, and founder of the Parallel Extensions to the .NET Framework team at Microsoft) detailed in Concurrent Programming on Windows p 373

Note that although Change is typed as returning a bool, it will actually never return anything but true. If there is a problem changing the timer-such as the target object already having been deleted-an exception will be thrown.

like image 102
Peter Ritchie Avatar answered Oct 28 '22 04:10

Peter Ritchie


This can in fact return false if the unmanaged extern ChangeTimerNative were to return false. However, this is awfully unlikely.

Take note to Microsoft's code:

bool status = false;
bool bLockTaken = false; 

// prepare here to prevent threadabort from occuring which could
// destroy m_lock state.  lock(this) can't be used due to critical
// finalizer and thinlock/syncblock escalation. 
RuntimeHelpers.PrepareConstrainedRegions();
try 
{ 
}
finally 
{
    do
    {
        if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0) 
        {
            bLockTaken = true; 
            try 
            {
                if (timerDeleted != 0) 
                    throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic"));
                status = ChangeTimerNative(dueTime,period);
            }
            finally 
            {
                m_lock = 0; 
            } 
        }
        Thread.SpinWait(1);     // yield to processor 
    }
    while (!bLockTaken);
}
return status; 

PLEASE NOTE that the ChangeTimerNative calls the ChangeTimerQueueTimer Windows API function so you can read that documentation to get a feel for how it might fail.

like image 38
Mike Perrenoud Avatar answered Oct 28 '22 04:10

Mike Perrenoud


On checking the managed source, the only case in which it returns false is if the AppDomain timer (if one does not exist, it is created) represented by a private class AppDomainTimerSafeHandle - has SafeHandle.IsInvalid set to true.

Since AppDomainTimerSafeHandle inherits from SafeHandleZeroOrMinusOneIsInvalid, IsInvalid is implemented by it - when a timer is attempted to be created by the unmanaged infrastructure and ends up with a Safe-Handle which is reading from the definition Zero-Or-Minus-One-Is-Invalid.

All cases point to this being extremely unlikely.

like image 33
Asti Avatar answered Oct 28 '22 04:10

Asti