Использование 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;
}
Имеются ли в первом случае какие-либо последствия для производительности, поскольку он блокирует размер метода?
Может ли вторая предложить безопасность, которую она могла бы подумать, - что-то ускользает от меня?
Есть ли другие способы сделать это надежно и желательно?