.Net中的闹钟应用程序

Mus*_*sis 11 .net c# time datetime

我不是在写闹钟应用程序,但它有助于说明我的问题.

假设我的应用程序中有一个方法,我希望每小时每小时调用一次该方法(例如,晚上7点,晚上8点,晚上9点等).我可以创建一个Timer并将其Interval设置为3600000,但最终这会与系统时钟不同步.或者我可以使用while()循环Thread.Sleep(n)来定期检查系统时间并在达到所需时间时调用方法,但我也不喜欢这个(Thread.Sleep(n)对我来说是一个很大的代码味道).

我正在寻找的是.Net中的一些方法,它允许我传入未来的DateTime对象和方法委托或事件处理程序,但我还没有找到任何这样的东西.我怀疑Win32 API中有一个方法可以做到这一点,但我也无法找到它.

Coi*_*oin 11

或者,您可以创建一个间隔为1秒的计时器,并每秒检查当前时间,直到达到事件时间,如果是,则提高您的事件.

你可以为它做一个简单的包装:

public class AlarmClock
{
    public AlarmClock(DateTime alarmTime)
    {
        this.alarmTime = alarmTime;

        timer = new Timer();
        timer.Elapsed += timer_Elapsed;
        timer.Interval = 1000;
        timer.Start();

        enabled = true;
    }

    void  timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        if(enabled && DateTime.Now > alarmTime)
        {
            enabled = false;
            OnAlarm();
            timer.Stop();
        }
    }

    protected virtual void OnAlarm()
    {
        if(alarmEvent != null)
            alarmEvent(this, EventArgs.Empty);
    }


    public event EventHandler Alarm
    {
        add { alarmEvent += value; }
        remove { alarmEvent -= value; }
    }

    private EventHandler alarmEvent;
    private Timer timer;
    private DateTime alarmTime;
    private bool enabled;
}
Run Code Online (Sandbox Code Playgroud)

用法:

AlarmClock clock = new AlarmClock(someFutureTime);
clock.Alarm += (sender, e) => MessageBox.Show("Wake up!");
Run Code Online (Sandbox Code Playgroud)

请注意上面的代码非常粗略,而且不是线程安全的.

  • 你要找的东西不存在. (4认同)
  • 您可以计算间隔而不是每秒检查一次. (4认同)

小智 8

有趣的是,我实际上遇到了一个非常类似的问题,并在.Net框架中寻找一种可以处理这种情况的方法.最后,我们最终实现了我们自己的解决方案,这是一个带有Thread.Sleep(n)的while循环的变体,其中n越小,越接近所需的目标时间(实际上是对数,但是有一些合理的阈值,所以当你接近目标时间时,你不是最大化cpu.)这是一个非常简单的实现,它只能在现在和目标时间之间休眠一半.

class Program
{
    static void Main(string[] args)
    {
        SleepToTarget Temp = new SleepToTarget(DateTime.Now.AddSeconds(30),Done);
        Temp.Start();
        Console.ReadLine();
    }

    static void Done()
    {
        Console.WriteLine("Done");
    }
}

class SleepToTarget
{
    private DateTime TargetTime;
    private Action MyAction;
    private const int MinSleepMilliseconds = 250;

    public SleepToTarget(DateTime TargetTime,Action MyAction)
    {
        this.TargetTime = TargetTime;
        this.MyAction = MyAction;
    }

    public void Start()
    {
        new Thread(new ThreadStart(ProcessTimer)).Start();
    }

    private void ProcessTimer()
    {
        DateTime Now = DateTime.Now;

        while (Now < TargetTime)
        {
            int SleepMilliseconds = (int) Math.Round((TargetTime - Now).TotalMilliseconds / 2);
            Console.WriteLine(SleepMilliseconds);
            Thread.Sleep(SleepMilliseconds > MinSleepMilliseconds ? SleepMilliseconds : MinSleepMilliseconds);
            Now = DateTime.Now;
        }

        MyAction();
    }
}
Run Code Online (Sandbox Code Playgroud)