为什么这个C#定时器代码不起作用?

时间:2009-09-23 01:10:44

标签: c# timer

我需要能够为我正在编写的应用程序一次禁用按钮1.5秒。显示图像,用户单击按钮,然后显示另一个图像。我需要确保用户不会再太快点击按钮。

因此,当显示图像时,我调用此函数:

    //when a new image is displayed, start the timer and disable the 'done' button
    //for 1.5 seconds, to force people to stop pressing next so quickly
    System.Timers.Timer mTimer;
    void TimerStart() {
        Done.IsEnabled = false;

        mTimer = new System.Timers.Timer();
        mTimer.Interval = 1500;
        mTimer.Start();
        mTimer.Elapsed += new System.Timers.ElapsedEventHandler(TimerEnd);
    }

TimerEnd代码如下:

    void TimerEnd(object sender, EventArgs eArgs) {
        if (sender == mTimer){
            Done.IsEnabled = true;
            mTimer.Stop();
        }
    }

“Done.IsEnabled”行被点击,但按钮未重新启用,计时器不会停止触发。我在这做错了什么?如果重要,这是一个WPF应用程序。

4 个答案:

答案 0 :(得分:7)

改为使用DispatcherTimer

DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(someInterval);
timer.Tick += new EventHandler(someEventHandler);
timer.Start();

private void someEventHandler(Object sender, EventArgs args)
{
//some operations
//if you want this event handler executed for just once
// DispatcherTimer thisTimer = (DispatcherTimer)sender;
// thisTimer.Stop();
}

答案 1 :(得分:2)

基本上你是试图去除按钮,以防止太快的点击。而不是使用计时器以毫秒为单位保存先前的点击时间,如果在短时间内再次点击该按钮,则忽略下一个事件。

答案 2 :(得分:1)

计时器事件在另一个线程上引发。使用winforms控件时,您需要确保Invoke来自调用它们的同一个线程。

答案 3 :(得分:0)

使用WPF时,无法保证对非UI线程上的UI控件所做的更新将按预期工作。在许多情况下,执行此操作时会出现异常。

在Timer elapsed处理程序中,您需要使用BeginInvoke / EndInvoke范例,并在其中放置启用逻辑的按钮,以确保此代码在UI线程上运行,而不是在Begin / End Invoke中运行

还有一个SynchnornizationContext,可以通过调用SynchronizationContext.Current来访问。在进行计时器调用之前,您需要对此进行缓存,因为在非UI线程中SynchronizationContext.Current将为null。

This链接也谈到了这一点。