立即启动.net System.Timers.Timer
我使用计时器以合理的长间隔(2分钟)定期运行事件。这很好用。但是,我希望在创建计时器时立即触发事件(而不是等待2分钟) 请注意,我不能仅仅通过调用该方法来实现这一点,因为它需要一些时间来运行,并且会阻塞应用程序。我需要定时器正常启动,并在单独的线程中运行事件 目前我能想到的最好的方法是对计时器进行子类化,并创建一个立即启动.net System.Timers.Timer,timer,Timer,我使用计时器以合理的长间隔(2分钟)定期运行事件。这很好用。但是,我希望在创建计时器时立即触发事件(而不是等待2分钟) 请注意,我不能仅仅通过调用该方法来实现这一点,因为它需要一些时间来运行,并且会阻塞应用程序。我需要定时器正常启动,并在单独的线程中运行事件 目前我能想到的最好的方法是对计时器进行子类化,并创建一个TriggerManually方法,该方法将执行以下操作: 关闭自动复位功能 将间隔设置为1ms 启用计时器 这将立即触发已过事件,我可以将所有设置恢复正常 但似乎有点迂回。有更好
TriggerManually
方法,该方法将执行以下操作:
- 关闭自动复位功能
- 将间隔设置为1ms
- 启用计时器
但似乎有点迂回。有更好的方法吗?可以改用System.Threading.Timer吗? 它有一个构造函数,允许您选择间隔和延迟(可以设置为0立即开始)。
您不能手动调用事件处理程序来处理已发生的事件吗 即使您希望它在线程池线程上执行,也可以调用它
class Blah
{
private Timer mTimer;
public Blah()
{
mTimer = new Timer(120000);
ElapsedEventHandler handler = new ElapsedEventHandler(Timer_Elapsed);
mTimer.Elapsed += handler;
mTimer.Enabled = true;
//Manually execute the event handler on a threadpool thread.
handler.BeginInvoke(this, null, new AsyncCallback(Timer_ElapsedCallback), handler);
}
private static void Timer_Elapsed(object source, ElapsedEventArgs e)
{
//Do stuff...
}
private void Timer_ElapsedCallback(IAsyncResult result)
{
ElapsedEventHandler handler = result.AsyncState as ElapsedEventHandler;
if (handler != null)
{
handler.EndInvoke(result);
}
}
}
我喜欢Rob Cooke的答案,所以我构建了一个小的
Timer
类,它将System.Timers.Timer
子类化,并添加了这个功能。(有来自的提示)
我知道我可以使用System.Threading.Timer
来代替,但这很简单,在我的应用程序中运行良好
/// <summary>
// EagerTimer is a simple wrapper around System.Timers.Timer that
// provides "set up and immediately execute" functionality by adding a
// new AutoStart property, and also provides the ability to manually
// raise the Elapsed event with RaiseElapsed.
/// </summary>
public class EagerTimer : Timer
{
public EagerTimer()
: base() { }
public EagerTimer(double interval)
: base(interval) { }
// Need to hide this so we can use Elapsed.Invoke below
// (otherwise the compiler complains)
private event ElapsedEventHandler _elapsedHandler;
public new event ElapsedEventHandler Elapsed
{
add { _elapsedHandler += value; base.Elapsed += value; }
remove { _elapsedHandler -= value; base.Elapsed -= value; }
}
public new void Start()
{
// If AutoStart is enabled, we need to invoke the timer event manually
if (AutoStart)
{
this._elapsedHandler.BeginInvoke(this, null, new AsyncCallback(AutoStartCallback), _elapsedHandler); // fire immediately
}
// Proceed as normal
base.Start();
}
private void AutoStartCallback(IAsyncResult result)
{
ElapsedEventHandler handler = result.AsyncState as ElapsedEventHandler;
if (handler != null) handler.EndInvoke(result);
}
// Summary:
// Gets or sets a value indicating whether the EagerTimer should raise
// the System.Timers.Timer.Elapsed event immediately when Start() is called,
// or only after the first time it elapses. If AutoStart is false, EagerTimer behaves
// identically to System.Timers.Timer.
//
// Returns:
// true if the EagerTimer should raise the System.Timers.Timer.Elapsed
// event immediately when Start() is called; false if it should raise the System.Timers.Timer.Elapsed
// event only after the first time the interval elapses. The default is true.
[Category("Behavior")]
[DefaultValue(true)]
[TimersDescription("TimerAutoStart")]
public bool AutoStart { get; set; }
/// <summary>
/// Manually raises the Elapsed event of the System.Timers.Timer.
/// </summary>
public void RaiseElapsed()
{
if (_elapsedHandler != null)
_elapsedHandler(this, null);
}
}
//
//Wangertimer是一个简单的System.Timers.Timer包装器
//通过添加
//新的AutoStart属性,还提供手动
//使用RaiseeExpressed引发已过去事件。
///
公共类计时器:计时器
{
公共图书馆
:base(){}
公共定时器(双间隔)
:基(间隔){}
//需要隐藏它,以便我们可以使用下面的appead.Invoke
//(否则编译器会抱怨)
私有事件ElapsedEventHandler _elapsedHandler;
公共新事件ElapsedEventHandler已过
{
添加{u elapsedHandler+=value;base.appeased+=value;}
删除{u elapsedHandler-=value;base.appeased-=value;}
}
公共新空开始()
{
//如果启用了AutoStart,则需要手动调用计时器事件
如果(自动启动)
{
this._elapsedHandler.BeginInvoke(this,null,new AsyncCallback(AutoStartCallback),_elapsedHandler);//立即激发
}
//照常进行
base.Start();
}
私有void AutoStartCallback(IAsyncResult结果)
{
ElapsedEventHandler handler=result.asynchState作为ElapsedEventHandler;
if(handler!=null)handler.EndInvoke(result);
}
//总结:
//获取或设置一个值,该值指示计时器是否应引发
//调用Start()时,System.Timers.Timer.Appeased事件立即发生,
//如果AutoStart为false,则计时器将运行
//与System.Timers.Timer相同。
//
//返回:
//如果计时器应升高System.Timers.Timer.Appeased,则为true
//调用Start()时立即发生事件;如果应引发System.Timers.Timer.Appeased,则为false
//事件。默认值为true。
[类别(“行为”)]
[默认值(真)]
[计时器说明(“计时器启动”)]
公共bool自动启动{get;set;}
///
///手动引发System.Timers.Timer的已用事件。
///
公开无效已失效()
{
如果(_elapsedHandler!=null)
_elapsedHandler(此,空);
}
}
单元测试
[TestClass]
public class Objects_EagerTimer_Tests
{
private const int TimerInterval = 10; // ms
private List<DateTime> _timerFires = new List<DateTime>();
private DateTime _testStart;
[TestInitialize]
public void TestSetup()
{
_timerFires.Clear();
_testStart = DateTime.Now;
}
[TestMethod]
public void Objects_EagerTimer_WithAutoStartDisabled()
{
// EagerTimer should behave as a normal System.Timers.Timer object
var timer = new EagerTimer(TimerInterval);
timer.AutoReset = false;
timer.Elapsed += timerElapsed;
timer.Start();
// Wait (not enough time for first interval)
Thread.Sleep(5);
Assert.IsFalse(_timerFires.Any());
// Wait a little longer
Thread.Sleep(TimerInterval);
Assert.AreEqual(1, _timerFires.Count);
}
[TestMethod]
public void Objects_EagerTimer_WithAutoStartEnabled()
{
// EagerTimer should fire immediately on Start()
var timer = new EagerTimer(TimerInterval);
timer.AutoReset = false;
timer.AutoStart = true;
timer.Elapsed += timerElapsed;
timer.Start();
// Wait (not enough time for first interval)
Thread.Sleep(5);
Assert.IsTrue(_timerFires.Any());
// Wait a little longer, now it will have fired twice
Thread.Sleep(TimerInterval);
Assert.AreEqual(2, _timerFires.Count);
}
[TestMethod]
public void Objects_EagerTimer_WhenRaisingManually()
{
// EagerTimer should fire immediately on Start()
var timer = new EagerTimer(TimerInterval);
timer.AutoReset = false;
timer.AutoStart = false;
timer.Elapsed += timerElapsed;
Assert.IsFalse(_timerFires.Any());
timer.RaiseElapsed();
Assert.IsTrue(_timerFires.Any());
}
private void timerElapsed(object sender, ElapsedEventArgs e) {
_timerFires.Add(DateTime.Now);
}
}
[TestClass]
公共类对象\u\u测试
{
private const int TimerInterval=10;//毫秒
私有列表_timerFires=新列表();
私有日期时间_testStart;
[测试初始化]
公共void TestSetup()
{
_timerFires.Clear();
_testStart=DateTime.Now;
}
[测试方法]
已禁用AutoStart()的公共无效对象
{
//计时器的行为应与正常的System.Timers.Timer对象相同
var定时器=新定时器(TimerInterval);
timer.AutoReset=false;
timer.appeased+=timerecursed;
timer.Start();
//等待(第一次间隔时间不足)
睡眠(5);
Assert.IsFalse(_timerFires.Any());
//再等一会儿
线程。睡眠(TimerInterval);
Assert.AreEqual(1,_timerFires.Count);
}
[测试方法]
具有AutoStart Enabled()的公共无效对象
{
//计时器应在启动时立即启动()
var定时器=新定时器(TimerInterval);
timer.AutoReset=false;
timer.AutoStart=true;
timer.appeased+=timerecursed;
timer.Start();
//等待(第一次间隔时间不足)
睡眠(5);
Assert.IsTrue(_timerFires.Any());
//再等一会儿,现在它已经发射两次了
线程。睡眠(TimerInterval);
Assert.AreEqual(2,_timerFires.Count);
}
[测试方法]
手动激活时的公共无效对象\u\u()
{
//计时器应在启动时立即启动()
var定时器=新定时器(TimerInterval);
timer.AutoReset=false;
timer.AutoStart=false;
timer.appeased+=timerecursed;
Assert.IsFalse(_timerFires.Any());
timer.raiseepersed();
Assert.IsTrue(_timerFires.Any());
}
私有void timerecursed(对象发送方,ElapsedEventArgs e){
_添加(DateTime.Now);
}
}
@Mitch-证明你是人类,尽管你的疯狂代表:)是的,这