如何使用计时器等待? [英] How to use a timer to wait?

查看:84
本文介绍了如何使用计时器等待?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过使用计时器来延迟方法中的事件,但是我不一定理解如何使用计时器来等待.

I am trying to delay events in my method by using a timer, however i do not necessarily understand how to use a timer to wait.

我将计时器设置为2秒,但是当我运行此代码时,最后一次调用的运行不会有2秒的延迟.

I set up my timer to be 2 seconds, but when i run this code the last call runs without a 2 second delay.

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秒,然后更改为第二".我在这里读了很多关于使用计时器而不是thread.sleep的线程,但是我似乎找不到/弄清楚如何实际实现它.

So when i click my button, it immediately shows label1 as "second", as opposed to changing to "first", waiting 2 seconds, then changing to "second". I have read lots of threads here about using timers instead of thread.sleep, but i cannot seem to find/figure out how to actually implement that.

推荐答案

timer.Start()只是启动计时器,但在计时器在后台运行时立即返回.因此,在将标签文本设置为 first second 之间几乎没有暂停.您要做的就是等待计时器计时,然后再次更新标签:

timer.Start() just starts the timer but immediately returns while the timer is running in the background. So between setting the label text to first and to second there is nearly no pause. What you want to do is wait for the timer to tick and only then update the label again:

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()启动计时器.

Btw. you should not set timer.Enabled to true, you are already starting the timer using timer.Start().

如评论中所述,您可以将计时器创建放入这样的方法中(注意:未经测试):

As mentioned in the comments, you could put the timer creation into a method, like this (note: this is untested):

public void Delayed(int delay, Action action)
{
    Timer timer = new Timer();
    timer.Interval = delay;
    timer.Tick += (s, e) => {
        action();
        timer.Stop();
    };
    timer.Start();
}

然后您可以像这样使用它:

And then you could just use it like this:

private void button1_Click(object sender, EventArgs e)
{
    label1.Text = "first";
    Delayed(2000, () => label1.Text = "second");
}

Tergiver的后续行动

使用Delayed是否包含内存泄漏(参考泄漏)?

Does using Delayed contain a memory leak (reference leak)?

订阅事件始终会创建双向引用.

Subscribing to an event always creates a two-way reference.

在这种情况下, timer.Tick 获得对匿名函数(lambda)的引用.该函数将提升局部变量 timer ,尽管它是一个引用而不是值,并且包含对传入的Action委托的引用.该委托将包含对 label1 ( Form 的实例成员)的引用.那么,是否有从 Timer Form 的循环引用?

In this case timer.Tick gets a reference to an anonymous function (lambda). That function lifts a local variable timer, 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 to label1, an instance member of the Form. So is there a circular reference from the Timer to the Form?

我不知道答案,我觉得很难推理.因为我不知道,所以我会在 Delayed 中删除lambda的使用,除了停止计时器(这是 sender 方法的参数),也请删除该事件.

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 the sender parameter of the method), also remove the event.

通常,lambda不会对垃圾收集造成问题.在这种情况下,计时器实例仅在本地存在,并且lambda中的引用不会阻止垃圾回收来收集实例(另请参见

Usually lambdas do not cause problems for the garbage collection. In this case, the timer instance only exists locally and the reference in the lambda does not prevent the garbage collection to collect the instances (see also this question).

我实际上是使用.NET Memory Profiler再次测试的.计时器对象被很好地收集,并且没有泄漏发生.探查器确实向我发出了警告,尽管有些情况是"[…]已被垃圾收集而没有得到适当处置".删除事件处理程序本身(通过保留对它的引用)并不能解决该问题.将捕获的计时器引用更改为(Timer)s 也没有改变.

I actually tested this again using the .NET Memory Profiler. The timer objects were collected just fine, and no leaking happened. The profiler did give me a warning that there are instances that "[…] have been garbage collected without being properly disposed" though. Removing the event handler in itself (by keeping a reference to it) did not fix that though. Changing the captured timer reference to (Timer)s did not change that either.

明显有帮助的是,在停止计时器后在事件处理程序中调用 timer.Dispose(),但是我认为这是否确实有必要.我认为事件探查器的警告/提示并不那么重要.

What did help—obviously—was to call a timer.Dispose() in the event handler after stopping the timer, but I’d argue if that is actually necessary. I don’t think the profiler warning/note is that critical.

这篇关于如何使用计时器等待?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆