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

时间:2012-03-15 17:40:25

标签: c# dst

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

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

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

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

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

谢谢。

3 个答案:

答案 0 :(得分:4)

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

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

在我的主要功能中,我产生了一个单独的线程如下:

new Thread(RunMessagePump).Start();

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

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

在此表单的FormLoad事件中,您可以声明任何System事件。在我的情况下,我有

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

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

干杯。

答案 1 :(得分:3)

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

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

您不需要非常频繁地运行它,因此它不会浪费大量资源。如果你找到更好的答案,你总是可以将它隐藏在一个API之后,可以用更高效的API替换它。)

答案 2 :(得分:0)

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