poller类有什么好的例子吗?具有等待句柄的线程安全,具有后台/前台选项以及常见的开始,停止,暂停,恢复呼叫?
我找到了像CruiseControl poller这样的例子,但理想情况下,我希望每次想要查询某些内容时都避免实现IPollable。
由于
答案 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,
}