使用System.Timers.Timer实例和Elapsed事件的事件处理程序时锁定

时间:2014-12-12 09:59:11

标签: c# multithreading timer .net-4.0

我在服务中有一个类来执行基于区间的操作。

它使用System.Timers.Timer类型的变量pollTimer和执行操作的事件方法。

鉴于这些event methods running from a thread pool,并且定时器本身的访问可以来自多个线程,我想保护对它的访问。

下面我的基本想法是否合理?

以下是基于ActionFunc的访问和使用的基本概念。

(注意:编辑历史记录显示了评论中建议的逐步更改)

    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.
            }
        }
    }

0 个答案:

没有答案