如何在C#中设置定时器以在特定时间执行

17

我有一个要求,需要每天凌晨00:01:00执行定时器...但是我不知道如何实现...如果我使用系统时间,它可能会以不同的格式呈现...以下是我的定时器代码:

static System.Timers.Timer timer;
timer = new System.Timers.Timer();
timer.Interval = 1000 * 60 * 60 * 24;//set interval of one day
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
start_timer(); 

static void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        // Add timer code here

    }
    private static void start_timer()
    {
        timer.Start();
    }

Nico的答案不准确也不可靠。Grant的答案是更好的解决方案,你需要轮询并检查DateTime.Now。 - Mick
4个回答

34
如果您想在凌晨00:01:00准确启动计时器并进行一些处理时间,然后重新启动计时器,您只需要计算当前时间Now与下一个00:01:00时间段之间的差异即可。
static Timer timer;
static void Main(string[] args)
{
    setup_Timer();
}

static void setup_Timer()
{
    DateTime nowTime = DateTime.Now;
    DateTime specificTime = new DateTime(nowTime.Year, nowTime.Month, nowTime.Day, 1, 0, 0, 0);
    if (nowTime > specificTime)
        specificTime= specificTime.AddDays(1);

    double tickTime = (specificTime- nowTime).TotalMilliseconds;
    timer = new Timer(tickTime);
    timer.Elapsed += timer_Elapsed;
    timer.Start();
}

static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    timer.Stop();
    //process code..
    setup_Timer();
}

2
这样行不通。计时器不够准确。http://stackoverflow.com/questions/10605639/timer-component-not-accurate-enough-is-there-an-alternative它测量滴答声,但它们可能会受到高CPU使用率的影响。 - Mick
一个更好的链接,描述为什么这是有问题的:https://dev59.com/qHRC5IYBdhLWcg3wFM_X - Mick
2
@Mick 这并不需要是一个实时问题。大约在凌晨1点或者1点零一秒,他想要发生某些事情。 定时器可能会有一些轻微的延迟,但对于大多数情况来说已经足够了。 对于这种情况,您可以使用MMTimer: http://www.codeproject.com/Articles/5501/The-Multimedia-Timer-for-the-NET-Framework - eran otzap

12
你需要做的是编写你所需的程序,然后使用操作系统内置的任务计划程序来启动它,这将是最可靠的。例如,Windows 的任务计划程序可以在用户登录前启动你的应用程序,处理必要时重新启动应用程序,记录错误并发送通知等。
否则,你需要让你的应用程序全天候运行,并定期轮询时间。
比如,你可以每分钟更改一次间隔时间:
timer.Interval = 1000 * 60;

在您的 Elapsed 事件中,检查当前时间:

static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    if (DateTime.Now.Hour == 1 && DateTime.Now.Minute == 0)
    {
        // do whatever
    }
}

但这真的不可靠。你的应用程序可能会崩溃。而处理DateTime可能会很棘手。


1
你可以用计算来得出它:
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    // Do stuff

    start_timer();
}

private static void start_timer()
{
    timer.Interval = CalculateInterval();
    timer.Start();
}

private static double CalculateInterval()
{
    // 1 AM the next day
    return (DateTime.Now.AddDays(1).Date.AddHours(1) - DateTime.Now).TotalMilliseconds;
}

https://dev59.com/qHRC5IYBdhLWcg3wFM_X - Mick

1
这里是一个计时器实现,它接受一个间隔参数(就像任何其他计时器一样),并在该间隔过期时精确触发,即使机器在此期间进入睡眠模式。
public delegate void TimerCallbackDelegate(object sender, ElapsedEventArgs e);
public class TimerAbsolute : System.Timers.Timer
{
    private DateTime m_dueTime;
    private TimerCallbackDelegate callback;

    public TimerAbsolute(TimerCallbackDelegate cb) : base()
    {
        if (cb == null)
        {
            throw new Exception("Call back is NULL");
        }
        callback = cb;
        this.Elapsed += this.ElapsedAction;
        this.AutoReset = true;
    }

    protected new void Dispose()
    {
        this.Elapsed -= this.ElapsedAction;
        base.Dispose();
    }

    public double TimeLeft
    {
        get
        {
            return (this.m_dueTime - DateTime.Now).TotalMilliseconds;
        }
    }

    public int TimeLeftSeconds
    {
        get
        {
            return (int)(this.m_dueTime - DateTime.Now).TotalSeconds;
        }
    }


    public void Start(double interval)
    {
        if (interval < 10)
        {
            throw new Exception($"Interval ({interval}) is too small");
        }

        DateTime dueTime = DateTime.Now.AddMilliseconds(interval);

        if (dueTime <= DateTime.Now)
        {
            throw new Exception($"Due time ({dueTime}) should be in future. Interval ({interval})");
        }
        this.m_dueTime = dueTime;

        // Timer tick is 1 second
        this.Interval = 1 * 1000;
        base.Start();
    }

    private void ElapsedAction(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (DateTime.Now >= m_dueTime)
        {
            // This means Timer expired
            callback(sender, e);
            base.Stop();
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接