2012-03-15 188 views
3

我在服务器上运行应用程序作为服务,然后我有多个客户端连接到该服务。我在每个客户端Window窗体应用程序上显示确切的服务器时间,因此我需要一种机制来检测服务器上的任何时间更改,以便我可以将其发送到客户端以进行显示。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事件只会在具有消息泵的应用程序(也就是必须有一个运行窗体)中激活。它在Visual Studio中工作,因为它在我作为非服务模式运行时具有表单。

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

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

因此,任何人都知道一个C#事件触发时间变化,在没有消息泵的应用程序中工作?我很惊讶,如果微软不包括这样的事件

谢谢。

+1

如果需要,SystemEvents类将在另一个线程上抽取消息循环。尝试一下。 – 2012-03-15 17:48:38

回答

3

谢谢大家的意见,他们肯定指出了我的正确方向。我能够解决我的问题,我想把他们放在这里,为任何人找到帮助。

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

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

new Thread(RunMessagePump).Start(); 

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

这个隐藏表单正是它的名字说,这是一个简单的表格,是保持由代码this.ResumeLayout隐藏的(假)在其Intiailaizecomponent()代码下。

在此表单的FormLoad事件中,您可以声明任何系统事件。在我来说,我有

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

瞧,这个精美的作品了,我想我会用这种形式加载事件捕捉我想用在道路上的任何SystemEvents。

干杯。

3

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

检测没有有用事件的手动时间更改稍微困难一点,但是您可以运行一个计时器,它每30秒执行一次并检查UTC时间是否“UTC时间至少是计时器计时器+ 30秒“有一定的宽容度?

你不需要经常运行它,所以它不会像是一个巨大的资源浪费。你总是可以隐藏此可与更高效的一个替代的API背后如果你找到一个更好的答案:)

0

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