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)
请注意上面的代码非常粗略,而且不是线程安全的.
小智 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)