Использование System.Threading.Timer
приводит к тому, что потоки запускаются из ThreadPool
, что означает, что, если интервал выполнения для таймера истекает, пока поток все еще обрабатывает в порядке предыдущего запроса, то тот же обратный вызов будет делегирован выполнить в другом потоке. Это, очевидно, вызовет проблемы в большинстве случаев, если обратный вызов не распознается вновь входящим, но мне интересно как сделать это лучшим (то есть безопасным) способом.
Допустим, у нас есть следующее:
ReaderWriterLockSlim OneAtATimeLocker = new ReaderWriterLockSlim();
OneAtATimeCallback = new TimerCallback(OnOneAtATimeTimerElapsed);
OneAtATimeTimer = new Timer(OneAtATimeCallback , null, 0, 1000);
Если весь Шебанг будет заблокирован, как таковой:
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'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;
}
Имеет ли первое влияние на производительность, поскольку оно блокируется для степени метода?
Может ли второй обеспечить безопасность, о которой можно подумать - это что-то ускользает от меня?
Есть ли другие способы сделать это надежно и желательно?