我设置了我的定时器为2秒,但是当我运行这个代码时,最后一个调用没有延迟2秒.
Timer timer = new Timer(); timer.Tick += new EventHandler(timer_Tick); // Everytime timer ticks,timer_Tick will be called timer.Interval = (1000) * (2); // Timer will tick evert second timer.Enabled = true; // Enable the timer void timer_Tick(object sender,EventArgs e) { timer.Stop(); } private void button1_Click(object sender,EventArgs e) { label1.Text = "first"; timer.Start(); label1.Text = "second"; }
所以当我点击我的按钮,它立即显示label1为“第二”,而不是改为“第一”,等待2秒,然后更改为“秒”.我已经阅读了很多线程关于使用timers而不是thread.sleep,但我似乎找不到/找出如何实际实现.
解决方法
void timer_Tick(object sender,EventArgs e) { timer.Stop(); label1.Text = "second"; } private void button1_Click(object sender,EventArgs e) { label1.Text = "first"; timer.Start(); }
顺便说一句.您不应将timer.Enabled设置为true,您已经使用timer.Start()启动定时器.
如注释所述,您可以将计时器创建放在一个方法中,像这样(注意:这是未经测试的):
public void Delayed(int delay,Action action) { Timer timer = new Timer(); timer.Interval = delay; timer.Tick += (s,e) => { action(); timer.Stop(); }; timer.Start(); }
然后你可以这样使用它:
private void button1_Click(object sender,EventArgs e) { label1.Text = "first"; Delayed(2000,() => label1.Text = "second"); }
Tergiver的后续行动
Does using Delayed contain a memory leak (reference leak)?
Subscribing to an event always creates a two-way reference.
In this case
timer.Tick
gets a reference to an anonymous function (lambda). That function lifts a local variabletimer
,though it’s a reference,not a value,and contains a reference to the passed in Action delegate. That delegate is going to contain a reference tolabel1
,an instance member of theForm
. So is there a circular reference from theTimer
to theForm
?I don’t know the answer,I’m finding it a bit difficult to reason about. Because I don’t know,I would remove the use of the lambda in
Delayed
,making it a proper method and having it,in addition to stopping the timer (which is thesender
parameter of the method),also remove the event.
通常,lambdas不会对垃圾收集造成问题.在这种情况下,定时器实例仅在本地存在,并且lambda中的引用不会阻止垃圾回收来收集实例(另见this question).
我实际上使用.NET内存分析器测试了这一点.定时器对象被收集得很好,没有发生泄漏.分析器确实给了我一个警告,有些情况下,“[…]已被垃圾收集,没有妥善处理”.删除事件处理程序本身(通过保留对它的引用)没有修复,虽然.将捕获的定时器引用更改为(定时器)也没有改变.
有什么帮助 – 显然是在停止定时器之后在事件处理程序中调用timer.Dispose(),但是我认为是否真的有必要.我不认为分析器警告/注释是至关重要的.