Использование System.Threading.Timer приводит к тому, что потоки откручиваются от ThreadPool, что означает, что если интервал выполнения для таймера истекает, когда поток все еще обрабатывается по порядку предыдущего запроса, то тот же обратный вызов будет делегирован для выполнения в другом потоке. Очевидно, что это вызовет проблемы в большинстве случаев, если обратный вызов не будет воспринят повторно, но мне интересно, как это сделать лучше всего (безопасно).
Скажем, мы имеем следующее:
ReaderWriterLockSlim OneAtATimeLocker = new ReaderWriterLockSlim();
OneAtATimeCallback = new TimerCallback(OnOneAtATimeTimerElapsed);
OneAtATimeTimer = new Timer(OneAtATimeCallback , null, 0, 1000);
Если весь shebang быть заблокирован, как таковой:
private void OnOneAtATimeTimerElapsed(object state)
{
if (OneAtATimeLocker.TryEnterWriteLock(0))
{
//get real busy for two seconds or more
OneAtATimeLocker.ExitWriteLock();
}
}
Или, нужно только управлять входом и выкидывать "нарушителей", как таковых:
private void OnOneAtATimeTimerElapsed(object state)
{
if (!RestrictOneAtATime())
{
return;
}
//get real busy for two seconds or more
if(!ReleaseOneAtATime())
{
//Well, Hell 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;
}
Имеются ли в первом случае какие-либо последствия для производительности, поскольку он блокирует размер метода?
Может ли вторая предложить безопасность, которую она могла бы подумать, - что-то ускользает от меня?
Есть ли другие способы сделать это надежно и желательно?