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

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

查看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事件仅在具有消息泵(也称为必须具有运行forms)的应用程序中激活。 它在Visual Studio中工作,因为当我将其作为非服务模式运行时,它有一个表单。

我可以通过选中“允许服务与桌面交互”选项来纠正这个问题,但这种做法违背了我尝试将应用程序作为服务运行的目的。

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

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

谢谢。

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

在没有有用事件的情况下检测手动时间变化稍微困难一些,但是你可以运行一个执行每(比如说)30秒的计时器并检查UTC时间是否不是“UTC时间至少计时器刻度+30秒”容忍量?

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

谢谢大家的投入,他们当然指出了我正确的方向。 我能够解决我的问题,并且我想把它们放在路上给那些发现它们有帮助的人。

所以在我运行服务的主程序中,它必须是ServiceBase的子类。

在我的主要function中,我产生了一个单独的线程,如下所示:

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

这个隐藏的forms正是它的名字所说的,它是一个简单的forms,它仍然被代码this.ResumeLayout(false)隐藏在其Intiailaizecomponent()代码下。

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

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

瞧,这很漂亮,我想我会使用这个表单加载事件来捕获我想要在路上使用的任何SystemEvent。

干杯。

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