检测夏令时甚至手动时间更改的C#事件

本文关键字:事件 时间 夏令时 检测 | 更新日期: 2023-09-27 18:27:51

我在服务器上将应用程序作为服务运行,然后让多个客户端连接到该服务。我在每个客户端窗口窗体应用程序上显示确切的服务器时间,因此我需要一种机制来检测服务器上的任何时间变化,以便将其发送到客户端进行显示。

查看MSDN,我发现SystemEvents.TimeChanged,我觉得我很幸运,因为当用Visual Studio测试下面的代码时,一切都很好:

SystemEvents.TimeChanged += new EventHandler(SystemEvents_TimeChanged);
static void SystemEvents_TimeChanged(object sender, EventArgs e)
    {
        //Occurs when user manually changes the time or due to
        //daylight saving time.  Server will issue its latest time
        //to all the clients so time can be adjusted.
    }

不幸的是,当我将其作为服务运行时,此事件永远不会被激发,因为从MSDN上的详细信息来看,TimeChanged事件只在消息泵(也就是说,它必须有一个运行表单)处于活动状态的应用程序中激发。它在VisualStudio中工作,因为当我以非服务模式运行它时,它有一个窗体。

我可以通过选中"允许服务与桌面交互"选项来纠正这一问题,但这与我尝试将应用程序作为服务运行的目的背道而驰。

我可以在应用程序中创建一个计时器滴答事件来检查时间变化,比如说每10秒左右,但这是一个很大的开销,只是为了检查服务器机器上每年发生两次或三次的随机时间变化。

所以,有人知道一个C#事件,它会在没有消息泵的应用程序中触发时间更改吗?如果微软不包括一个以这种方式工作的活动,我会感到惊讶

谢谢。

检测夏令时甚至手动时间更改的C#事件

感谢大家的投入,他们无疑为我指明了正确的方向。我能够解决我的问题,我想把它们放在这里,供以后发现它们有用的人使用。

因此,在我运行服务的主程序中,它必须是ServiceBase的一个子类。

在我的主函数中,我派生了一个单独的线程,如下所示:

new Thread(RunMessagePump).Start();
private void RunMessagePump()
{
  Application.Run(new HiddenForm())
}

这个隐藏的形式正是它的名字所说的,它是一个被代码隐藏的简单形式。ResumeLayout(false)在其Intailializecomponent()代码下。

在该表单的FormLoad事件中,您可以声明任何系统事件。就我而言,我有

private void HiddenForm_Load(object sender,EventArgs e)
{
  SystemEvents.timeChanged += new EventHandler(SystemEvents_TimeChanged);
}

Voila,这做得很好,我想我会使用这个表单加载事件来捕获我以后想要使用的任何SystemEvents。

干杯。

我强烈建议不要依赖本地时间开始。使用服务器的UTC时间,然后如果您需要将其转换为本地时间,只要您知道其时区,就可以在任何您想做的地方进行转换。

在没有有用事件的情况下检测手动时间更改稍微困难一些,但你能不能运行一个每隔(比如)30秒执行一次的计时器,并在一定的容差范围内检查UTC时间是否不是"UTC时间至少计时器刻度+30秒"?

你不需要经常运行它,所以这不会是对资源的巨大浪费。您可以始终将其隐藏在API后面,如果您找到更好的答案,可以用更高效的API替换:)

也许不太理想,您可以在前台运行一个代理,侦听TimeChanged事件并将其转发给您的服务。