简体   繁体   English

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

[英]C# event to detect Daylight Saving or even manual time change

I run an application as a service on a server and then I have multiple clients connect to that service. 我在服务器上运行应用程序作为服务,然后我有多个客户端连接到该服务。 I display the exact server time on each of the client Window form application and because of that I need a mechanism to detect any time change on the server so that I can send it to the client to display. 我在每个客户端窗体表单应用程序上显示确切的服务器时间,因此我需要一种机制来检测服务器上的任何时间更改,以便我可以将其发送到客户端进行显示。

Looking over the MSDN I found SystemEvents.TimeChanged , I thought I'm in luck because when testing with the code below with Visual Studio everything works great: 查看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.
    }

Unfortunately when I run this as a service, this event will never get fired because looking at the fine print on MSDN, the TimeChanged event only fires in an application with a message pump (aka it has to have a running form) active. 不幸的是,当我将其作为服务运行时,此事件永远不会被解雇,因为在MSDN上查看精细打印,TimeChanged事件仅在具有消息泵(也称为必须具有运行表单)的应用程序中激活。 It works in Visual Studio because it has a form when I run it as a non service mode. 它在Visual Studio中工作,因为当我将其作为非服务模式运行时,它有一个表单。

I can correct this by checking the option "Allow service to interact with desktop" but that kind of defeats the purpose of me trying to run the application as a service. 我可以通过选中“允许服务与桌面交互”选项来纠正这个问题,但这种做法违背了我尝试将应用程序作为服务运行的目的。

I could create a timer tick event in the application to check for time change, let's say every 10 seconds or so but this is a big overhead just to check for a random time change that occurs on the server machine twice or maybe 3 times per year. 我可以在应用程序中创建一个计时器刻度事件来检查时间变化,让我们说每10秒左右但这只是一个很大的开销,只是为了检查服务器机器上每年发生两次或每次3次的随机时间变化。

So anyone know a C# event that trigger on time change that works in an application that does not have message pump going? 所以任何人都知道一个C#事件触发时间更改,该事件在没有消息泵的应用程序中有效吗? I'm surprise if Microsoft does not include an event that works this way 如果微软不包含以这种方式运作的事件,我会感到惊讶

Thank you. 谢谢。

Thank you all for your inputs, they certainly pointed me in the right direction. 谢谢大家的投入,他们当然指出了我正确的方向。 I was able to solve my issue and I figure to put them here for anyone down the road that find them helpful. 我能够解决我的问题,我想把它们放在路上给那些发现它们有用的人。

So in my main program where I run the service, it has to be a sub class of ServiceBase. 所以在我运行服务的主程序中,它必须是ServiceBase的子类。

In my main function I spawned a separate thread as follow: 在我的主要功能中,我产生了一个单独的线程,如下所示:

new Thread(RunMessagePump).Start();

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

This Hidden form is exactly what its name say, it is a simple form that is remain hidden by the code this.ResumeLayout(false) under its Intiailaizecomponent() code. 这个隐藏的形式正是它的名字所说的,它是一个简单的形式,它仍然被代码this.ResumeLayout(false)隐藏在其Intiailaizecomponent()代码下。

Within this form's FormLoad event you can declare any System event. 在此表单的FormLoad事件中,您可以声明任何System事件。 In my case I have 就我而言,我有

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

Voila, this works out beautifully, and I think I will use this form load event to capture any SystemEvents I want to use down the road. 瞧,这很漂亮,我想我会使用这个表单加载事件来捕获我想要在路上使用的任何SystemEvent。

Cheers. 干杯。

Well I would strongly suggest not relying on the local time to start with. 那么我强烈建议不要依赖当地时间开始。 Use the UTC time of the server, and then if you need to convert that to the local time you can do that wherever you want to, if you know its time zone. 使用服务器的UTC时间,然后如果您需要将其转换为本地时间,您可以在任何您想要的地方进行转换,如果您知道它的时区。

Detecting a manual time change without a useful event is slightly tougher, but could you just run a timer which executes every (say) 30 seconds and checks whether the UTC time isn't "UTC time at least timer tick + 30 seconds" with some amount of tolerance? 在没有有用事件的情况下检测手动时间变化稍微困难一些,但是你可以运行一个执行每(比如说)30秒的计时器并检查UTC时间是否不是“UTC时间至少计时器刻度+ 30秒”容忍量?

You don't need to run it terribly often, so it's not like it's going to be a huge waste of resources. 你不需要经常运行它,所以它不会像是浪费大量资源。 You could always hide this behind an API which can be replaced with a more efficient one if you ever do find a better answer :) 你总是可以隐藏此可与更高效的一个替代的API背后,如果你真找到一个更好的答案:)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM