Using a System.Threading.Timer
导致线程从ThreadPool
,这意味着如果计时器的执行间隔到期,而线程仍在按先前请求的顺序处理,则相同的回调将被委托在另一个线程上执行。在大多数情况下,这显然会导致问题,除非回调是可重入感知的,但我想知道how以最好(即安全)的方式进行。
假设我们有以下内容:
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'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;
}
第一个是否有任何性能影响,因为它锁定了方法的范围?
第二个是否提供了人们可能认为的安全感——有什么东西在逃避我吗?
还有其他方法可以可靠且更好地解决此问题吗?
有很多方法可以处理这个问题。一种简单的方法是不让计时器周期性,只需设置dueTime争论。然后在finally 块的回调中重新启用计时器。这保证了回调不能同时运行。
这当然是通过回调的执行时间来使间隔变量。如果这是不可取的,并且回调只是偶尔需要比计时器周期长的时间,那么一个简单的锁就可以完成工作。另一种策略是 Monitor.TryEnter,如果返回 false,则放弃回调。这些都不是特别优秀,选择你最喜欢的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)