1

我写了几个不同的应用程序,它们显示时间。运行应用程序的机器在 Windows 7 上,无法访问互联网。

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

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

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

4

3 回答 3

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 线程。

于 2013-07-02T06:36:15.363 回答
0

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

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

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

于 2013-07-02T06:36:13.750 回答
-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;
    }
}

}

于 2016-05-02T14:53:31.720 回答