System.Timers.Timer延迟挂起应用程序

时间:2011-08-12 14:18:40

标签: c# timer

我遇到System.Timers.Timer对象的问题。我使用timer对象定期执行任务。在timer构造函数中,我调用执行工作的方法(DoTimeCheck()),以确保任务在启动时也运行一次。工作(定期)在BackgroundWorker中完成。

我用这个打电话给计时器:

 UpdaterTimer ut = UpdaterTimer.UpdaterTimerInstance;

我的问题是我需要用3分钟(在应用程序启动时运行的那个)延迟第一次运行任务。后续运行(Elapsed事件)应该立即运行。我想通过调用

来做到这一点
System.Threading.Thread.Sleep(TimeToDelayFirstRunInMiliseconds);

但这失败了,因为它还挂起了应用程序(主线程)的UI,使其无法使用。如何在不挂起UI的情况下延迟第一次运行DoTimeCheck()? 计时器的代码如下。如果问题没有以清晰的方式呈现,请告诉我,我将进行编辑。提前谢谢。

  public sealed class UpdaterTimer : Timer
{
    private static readonly UpdaterTimer _timer = new UpdaterTimer();
    public static UpdaterTimer UpdaterTimerInstance
    {
        get { return _timer; }
    }

    static UpdaterTimer()
    {
        _timer.AutoReset = true;
        _timer.Interval = Utils.TimeBetweenChecksInMiliseconds;
        _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
        _timer.Start();
        DoTimeCheck();

    }

    static void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        DoTimeCheck();
    }

    private static void DoTimeCheck()
    {
        //... work here 
    }
}

7 个答案:

答案 0 :(得分:4)

这样做的一种方法是给定时器间隔一个初始值(例如3分钟)。然后,在您的Elapsed事件处理程序中,您可以将间隔更改为从那时起将使用的常规值。

 _timer.Interval = Utils.InitialCheckInterval;

 static void _timer_Elapsed(object sender, ElapsedEventArgs e)
 {
     if (_timer.Interval == Utils.InitialCheckInterval)
     {
         _timer.Interval = Utils.RegularCheckInterval;
     }

     DoTimeCheck();
 }

答案 1 :(得分:1)

你在主/ GUI线程上调用Sleep(TimeToDelayFirstRunInMiliseconds);似乎(虽然你没有显示那些代码),这就是导致你的UI线程挂起的原因。相反,您应该将计时器设置为在第一次运行时延迟3分钟,然后一旦运行,您再次更改计时器以按照您希望的所有后续运行的频率运行。

答案 2 :(得分:1)

你似乎已经很好地使用计时器了。在启动另一个计时器之前,只需使用另一个延迟三分钟。

timer = new Timer();
timer.AutoReset = false;
timer.Interval = 3*60*1000;
timer.Elapsed += startOtherTimerMethod;
timer.Start();

编辑:我应该注意到这与Peter Kelly的回答大致相同,只是他的解决方案更优雅,因为它只使用一个计时器,没有额外的方法,并利用了这个事实计时器在运行之间是可变的。如果你喜欢这个答案,你会爱上他的。 ; - )

答案 3 :(得分:1)

您的UI驻留在同一个线程上,因此当您将线程置于休眠状态时,它也会导致您的UI挂起。您需要在另一个线程上运行计时器。

答案 4 :(得分:0)

您的UI需要一个单独的线程,目前您还在使用UI。检查this post

答案 5 :(得分:0)

在这种情况下你不应该使用thread.sleep你应该使用winforms控件

从不锁定主UI的BackgroundWorker。你可以在那里写下你的逻辑。

这里的例子: http://www.knowdotnet.com/articles/backgroundworker.html

答案 6 :(得分:0)

使用System.Threading.Timer - 构造函数接受第一次运行延迟的参数和后续运行的间隔。