我在服务中有一个类来执行基于区间的操作。
它使用System.Timers.Timer类型的变量pollTimer
和执行操作的事件方法。
鉴于这些event methods running from a thread pool,并且定时器本身的访问可以来自多个线程,我想保护对它的访问。
下面我的基本想法是否合理?
(注意:编辑历史记录显示了评论中建议的逐步更改)
private readonly object pollTimerLock = new object();
private Timer pollTimer;
private enum NullPollTimerFailureMode { Continue, Fail };
private void RunOnLockedPollTimer(NullPollTimerFailureMode nullPollTimerFailureMode, Action<Timer> action)
{
Timer timer = pollTimer;
if (null == timer)
{
if (NullPollTimerFailureMode.Fail == nullPollTimerFailureMode)
throw new GenericException<SimplePoll>("unexpected null pollTimer");
// else: NOP
}
else
{
lock (pollTimerLock)
action(timer);
}
}
private TResult RunOnLockedPolltimer<TResult>(TResult defaultResult, Func<Timer, TResult> action)
{
TResult result = defaultResult;
RunOnLockedPolltimer(NullPollTimerFailureMode.Continue,
lockedPolltimer =>
{
result = action(lockedPolltimer);
});
return result;
}
(方法现在是私有的,因为它是封装行为的类的内部)
一些访问模式:
获得状态:
bool result = RunOnLockedPolltimer(false,
lockedPolltimer => lockedPolltimer.Enabled);
禁用计时器:
RunOnLockedPolltimer(NullPollTimerFailureMode.Continue,
lockedPolltimer =>
lockedPolltimer.Enabled = false);
启用计时器:
RunOnLockedPolltimer(NullPollTimerFailureMode.Fail,
lockedPolltimer =>
{
lockedPolltimer.AutoReset = true;
lockedPolltimer.Enabled = true;
});
事件:我应该在这里使用RunOnLockedPolltimer
吗?
private void PollTimerElapsed(object sender, ElapsedEventArgs e)
{
try
{
if (!IsPolling)
return;
// Ensure only one event on the timer can run at the same time
RunOnLockedPollTimer(NullPollTimerFailureMode.Fail,
lockedPollTimer => LockedPollTimerElapsed());
}
catch (Exception exception)
{
try
{
Logger.LogException("PollTimerElapsed", InformationLevel.Critical, exception);
}
catch
{
// if logging fails, don't let exceptions exit the PollTimerElapsed eventhandler.
}
}
}