gpt4 book ai didi

c# - 使用 System.Threading.Timer 和 Monitor 的线程安全执行

转载 作者:太空狗 更新时间:2023-10-29 22:28:35 25 4
gpt4 key购买 nike

使用 System.Threading.Timer 会导致线程从 ThreadPool 中旋转,这意味着如果计时器的执行间隔到期而线程仍在处理按照先前请求的顺序,相同的回调将被委托(delegate)在另一个线程上执行。在大多数情况下,这显然会导致问题,除非回调是可重入感知的,但我想知道如何以最好的(意味着安全的)方式解决它。

假设我们有以下内容:

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 block 的回调中重新启用计时器。这保证了回调不能同时运行。

这当然是通过回调的执行时间来使间隔可变。如果这是不可取的,并且回调只是偶尔需要比定时器周期更长的时间,那么一个简单的锁就可以完成工作。另一种策略是 Monitor.TryEnter,如果它返回 false,就放弃回调。这些都不是特别优越,选择你最喜欢的。

关于c# - 使用 System.Threading.Timer 和 Monitor 的线程安全执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5124252/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com