c#中是否有任何标准的Poller示例类

时间:2011-08-24 09:40:10

标签: c# multithreading polling

poller类有什么好的例子吗?具有等待句柄的线程安全,具有后台/前台选项以及常见的开始,停止,暂停,恢复呼叫?

我找到了像CruiseControl poller这样的例子,但理想情况下,我希望每次想要查询某些内容时都避免实现IPollable。

由于

2 个答案:

答案 0 :(得分:1)

我不知道除了基本的.NET计时器类之外的标准类,但这里是.NET计时器的包装类,它使用委托而不是您找到的包装器的IPollable接口。它还具有一些锁定功能和一些派上用场的方法。例如,您可能希望自己扩展和改进暂停/恢复和日志记录。祝你好运。

public class TimerWrapper
{
    private object defaultLock = new object();
    private object functionLock = null;
    private object classLock = new object();
    protected bool isRunning = false;
    protected bool isRepeating = false;
    protected Timer timer = null;
    protected Action timerFn = null;

    public TimerWrapper(Action timerFn)
    {
        if (timerFn == null)
        {
            throw new ArgumentNullException("timerFn", "Invalid timer delegate supplied at construction");
        }
        // Execute this function upon expiration of the timer
        this.timerFn = timerFn;
    }

    public TimerWrapper(Action timerFn, ref object timerLock) : this(timerFn)
    {
        // Use the locking object passed at construction
        this.functionLock = timerLock;
    }

    protected void TimerFunction(object state)
    {
        if (timerFn != null)
        {
            lock (classLock)
            {
                // Lock on function lock if available or default lock otherwise
                lock (functionLock ?? defaultLock)
                {
                    // If timer isn't repeating it's now no longer running
                    if (!IsRepeating)
                    {
                        IsRunning = false;
                    }

                    // Execute this function because timer has expired
                    timerFn();
                }
            }
        }
    }

    public void Stop()
    {
        lock (classLock)
        {
            if (timer != null)
            {
                timer.Dispose();
                timer = null;
            }

            IsRunning = false;
        }
    }

    public void Start(int duetime)
    {
        // Start the timer for a single run
        Start(duetime, Timeout.Infinite);
    }

    public void Start(int duetime, int period)
    {
        if (duetime > 0)
        {
            lock (classLock)
            {
                // Stop the timer
                Stop();

                // Start the timer for either a single run or repeated runs
                timer = new Timer(TimerFunction, null, duetime, period);

                IsRunning = true;
                IsRepeating = (period != Timeout.Infinite);
            }
        }
    }

    public bool IsRepeating
    {
        get
        {
            return isRepeating;
        }
        protected set
        {
            if (isRepeating != value)
            {
                isRepeating = value;
            }
        }
    }

    public bool IsRunning
    {
        get
        {
            return isRunning;
        }
        protected set
        {
            if (isRunning != value)
            {
                isRunning = value;
            }
        }
    }
}

答案 1 :(得分:1)

感谢mtijn,看看你的例子并编写了我自己的poller,它完成了poller应该做的所有事情。任何评论都表示赞赏。

public class Poller
{
    private static readonly ILog _log = LogManager.GetLogger(typeof(Poller));

    private readonly Action _action;
    private readonly int _pollingInterval;
    private readonly Thread _processingThread;
    private readonly AutoResetEvent _stopEvent;
    private readonly ManualResetEventSlim _pauseEvent;
    private readonly object _syncLock = new object();
    private PollerState _pollerState;

    public Poller(string pollerName, Action action, int pollingInterval, bool isBackground)
    {
        _action = action;
        _pollingInterval = pollingInterval;

        _stopEvent = new AutoResetEvent(false);
        _pauseEvent = new ManualResetEventSlim(false);
        _processingThread = new Thread(DoWork) { IsBackground = isBackground, Name = pollerName };

        _pollerState = PollerState.Unstarted;
    }

    public void Start()
    {
        _pollerState = PollerState.Running;
        _processingThread.Start();
    }

    public void Start(int dueTime)
    {
        new Timer(o => Start(), null, dueTime, Timeout.Infinite);
    }

    public void Stop()
    {
        lock (_syncLock)
        {
            if (_pollerState != PollerState.Running && _pollerState != PollerState.PauseRequested)
                _log.WarnFormat("Requested STOP on {0} poller state.", _pollerState);

            _pollerState = PollerState.StopRequested;
            _stopEvent.Set();
            _pauseEvent.Set();
        }
    }

    public void Pause()
    {
        lock (_syncLock)
        {
            if (_pollerState != PollerState.Running)
                _log.WarnFormat("Requested PAUSE on {0} poller state.", _pollerState);

            _pauseEvent.Reset();
            _pollerState = PollerState.PauseRequested;
        }
    }

    public void Continue()
    {
        lock(_syncLock)
        {
            if (_pollerState == PollerState.PauseRequested)
                _pollerState = PollerState.Running; // applicable if job is long running or no new poll was needed since pause requested
            else if (_pollerState != PollerState.Paused)
                _log.WarnFormat("Requested CONTINUE on {0} poller state.", _pollerState);
            _pauseEvent.Set();
        }
    }

    private void DoWork()
    {
        while (_pollerState == PollerState.Running)
        {
            try
            {
                _action();
            }
            catch(Exception ex)
            {
                _log.Error(Thread.CurrentThread.Name + "failed.", ex);
            }
            finally
            {
                if (_stopEvent.WaitOne(_pollingInterval))
                {
                    if (_pollerState == PollerState.StopRequested)
                        _pollerState = PollerState.Stopped;
                }

                if (_pollerState == PollerState.PauseRequested)
                {
                    _pollerState = PollerState.Paused;
                    _pauseEvent.Wait();
                    // Continue only if we are still in Pause mode and not StopRequested
                    if (_pollerState == PollerState.Paused)
                        _pollerState = PollerState.Running;
                }
            }
        }
        _log.Debug("Exiting: " + Thread.CurrentThread.Name);
    }
}
public enum PollerState
{
    Unstarted = 0,
    Running = 1,
    StopRequested = 2,
    Stopped = 3,
    PauseRequested = 4,
    Paused = 5,
}