Using a System.Threading.Timer
results in threads being spun from a ThreadPool
, which means if the interval of execution for the timer expires while a thread is still processing by order of a previous request, then the same callback will be delegated to execute on another thread. This is obviously going to cause problems in most cases unless the callback is re-entrant aware, but I'm wondering how to go about it the best (meaning safe) way.
Let's say we have the following:
ReaderWriterLockSlim OneAtATimeLocker = new ReaderWriterLockSlim();
OneAtATimeCallback = new TimerCallback(OnOneAtATimeTimerElapsed);
OneAtATimeTimer = new Timer(OneAtATimeCallback , null, 0, 1000);
Should the whole shebang be be locked down, as such:
private void OnOneAtATimeTimerElapsed(object state)
{
if (OneAtATimeLocker.TryEnterWriteLock(0))
{
//get real busy for two seconds or more
OneAtATimeLocker.ExitWriteLock();
}
}
Or, should only entry be managed, and kick out 'trespassers', as such:
private void OnOneAtATimeTimerElapsed(object state)
{
if (!RestrictOneAtATime())
{
return;
}
//get real busy for two seconds or more
if(!ReleaseOneAtATime())
{
//Well, Hell's bells and buckets of blood!
}
}
bool OneAtATimeInProgress = false;
private bool RestrictToOneAtATime()
{
bool result = false;
if (OneAtATimeLocker.TryEnterWriteLock(0))
{
if(!OneAtATimeInProgress)
{
OneAtATimeInProgress = true;
result = true;
}
OneAtATimeLocker.ExitWriteLock();
}
return result;
}
private bool ReleaseOneAtATime()
{
bool result = false;
//there shouldn't be any 'trying' about it...
if (OneAtATimeLocker.TryEnterWriteLock(0))
{
if(OneAtATimeInProgress)
{
OneAtATimeInProgress = false;
result = true;
}
OneAtATimeLocker.ExitWriteLock();
}
return result;
}
Does the first have any performance implications because it locks for the extent of the method?
Does the second even offer the safety one might think it does - is something escaping me?
Are there any other ways to go about this reliably, and preferably?