using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace Aitex.DataAnalysis.Core { public class PeriodicJob { Thread _thread; int _interval; int _tick = 0; Func _func; CancellationTokenSource _cancelFlag = new CancellationTokenSource(); //for quit thread ManualResetEvent _waitFlag = new ManualResetEvent(true); //for pause purpose ManualResetEvent _sleepFlag = new ManualResetEvent(false); //for sleep time public PeriodicJob(int interval, Func func, string name, bool isStartNow=false, bool isBackground=true) { _thread = new Thread(new ParameterizedThreadStart(ThreadFunction)); _thread.Name = name; _thread.IsBackground = true; _interval = interval; _func = func; if (isStartNow) Start(); } public void Start() { if (_thread == null) return; _waitFlag.Set(); if (_thread.IsAlive) return; _thread.Start(this); } public void Pause() { _waitFlag.Reset(); } public void Stop() { _sleepFlag.Set(); //do not sleep _waitFlag.Set(); //do not pause _cancelFlag.Cancel(); //quit _thread.Abort(); _thread.Join(); _thread = null; } void ThreadFunction(object param) { PeriodicJob t = (PeriodicJob)param; t.Run(); } void Run() { while (!_cancelFlag.IsCancellationRequested) { _tick = Environment.TickCount; _waitFlag.WaitOne(); if (!_func()) break; _sleepFlag.WaitOne(Math.Max(_interval - (Environment.TickCount - _tick), 30)); } } } }