同步本地应用程序之间的时间

时间:2013-07-02 06:32:07

标签: c#

我写了几个不同的应用程序,显示时间。运行应用程序的计算机位于Windows 7上,无法访问Internet。

当前实现是每个应用程序中的一个计时器,间隔为1000毫秒,并抓取DateTime.Now来显示它。不幸的是,这也意味着应用程序在视觉上不会彼此同步,更糟糕的情况是应用程序显示的时间比另一个慢999ms。 “滞后/尾随”非常明显,即使它们都在第二个范围内。

我可以将计时器更改为100毫秒间隔,但我不确定从长远来看它会如何影响CPU资源?我还被告知我可以使用“Windows Interupt”,它会在系统时钟更新时触发,但我似乎无法找到任何信息。有人能指出我正确的方向吗?

我不需要在应用程序中与彼此完全同步(以毫秒为单位)的时间,足以让人眼看到它们在一起滴答。

3 个答案:

答案 0 :(得分:1)

您可以使用EventWaitHandle对象构造每个进程可以锁定或阻止的命名事件。每次应用程序更新时间时,您都可以在所有其他应用程序中执行相同的操作。

好的,一些演示代码(未测试):

class TimeSyncTest {
    EventWaitHandle _timeSync;
    System.Windows.Forms.Timer _refreshTimer;

    void DoTimeSync() {
        bool wasNew;
        _timeSync = new EventWaitHandle(false, EventResetMode.ManualReset, "TimeSync", out wasNew);
        if (wasNew) {
            _refreshTimer = new System.Windows.Forms.Timer() { Interval = 60000 };
            _refreshTimer.Tick += new EventHandler(_refreshTimer_Tick);
            _refreshTimer.Start();
        } else {
            WaitForMasterToTick();
        }
    }

    private void WaitForMasterToTick() {
        do {
            _timeSync.WaitOne();
            RefreshTime();
        } while (true);
    }

    void _refreshTimer_Tick(object sender, EventArgs e) {
        _timeSync.Set();
        RefreshTime();
        _timeSync.Reset();
    }

    void RefreshTime() {
    }
}

当“主”应用程序关闭时,此代码无法处理,其余的将不再更新,您可能还希望运行WaitForMasterToTick以在单独的线程中运行,因为这将阻止gui线程。

答案 1 :(得分:0)

使用Windows时间服务不是解决方案吗?为什么重新发明轮子?

“虽然Windows时间服务不是网络时间协议(NTP)的精确实现,但它使用NTP规范中定义的复杂算法套件,以确保整个网络中计算机上的时钟与理想情况下,AD DS域中的所有计算机时钟都与权威计算机的时间同步。许多因素都会影响网络上的时间同步。“

http://technet.microsoft.com/en-us/library/cc773013(v=ws.10).aspx

答案 2 :(得分:-1)

using System.Net;
using System.Net.Sockets;

命名空间时钟 {     公共部分类Form1:表格     {         公共Form1()         {             的InitializeComponent();         }

    private void button1_Click(object sender, EventArgs e)
    {
        label1.Text = GetNetworkTime().ToString(); //show date and time in label1
    }

    public static DateTime GetNetworkTime()
    {
        const string ntpServer = "time.windows.com";
        /*
        time-a.nist.gov                 129.6.15.28 NIST, Gaithersburg, Maryland
        time-b.nist.gov                 129.6.15.29 NIST, Gaithersburg, Maryland
        time-a.timefreq.bldrdoc.gov     132.163.4.101   NIST, Boulder, Colorado
        time-b.timefreq.bldrdoc.gov     132.163.4.102   NIST, Boulder, Colorado
        time-c.timefreq.bldrdoc.gov     132.163.4.103   NIST, Boulder, Colorado
        utcnist.colorado.edu            128.138.140.44  University of Colorado, Boulder
        time.nist.gov                   192.43.244.18   NCAR, Boulder, Colorado
        time-nw.nist.gov                131.107.1.10    Microsoft, Redmond, Washington
        nist1.datum.com                 209.0.72.7  Datum, San Jose, California
        nist1.dc.certifiedtime.com      216.200.93.8    Abovnet, Virginia
        nist1.nyc.certifiedtime.com     208.184.49.9    Abovnet, New York City
        nist1.sjc.certifiedtime.com     208.185.146.41  Abovnet, San Jose, California
        */
        var ntpData = new byte[48];
        ntpData[0] = 0x1B; //LeapIndicator = 0 (no warning), VersionNum = 3 (IPv4 only), Mode = 3 (Client Mode)

        var addresses = Dns.GetHostEntry(ntpServer).AddressList;
        var ipEndPoint = new IPEndPoint(addresses[0], 123);
        var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        socket.Connect(ipEndPoint);
        socket.Send(ntpData);
        socket.Receive(ntpData);
        socket.Close();

        ulong intPart = (ulong)ntpData[40] << 24 | (ulong)ntpData[41] << 16 | (ulong)ntpData[42] << 8 | (ulong)ntpData[43];
        ulong fractPart = (ulong)ntpData[44] << 24 | (ulong)ntpData[45] << 16 | (ulong)ntpData[46] << 8 | (ulong)ntpData[47];

        var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
        DateTime networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);

        return networkDateTime;
    }
}

}