小编Hei*_*tes的帖子

什么是.NET应用程序最稳定的时间戳源?

基础问题

我的C#应用​​程序中存在时间戳问题.我异步地从远程TCP连接接收数据.每次收到数据时,我都会将时间戳变量更新为DateTime.Now.在一个单独的线程上,每秒一次,我检查它是否超过自我上次收到后的预定义超时时间,如果是,则断开连接.这种方法已经工作了很多年,但现在我的情况是应用程序安装在具有不稳定时间源的机器上.每隔几天,机器时间"自动校正",我提前断开连接.代码基本如下:

接收流程

void OnReceiveComplete(IAsyncResult ar) {
    ...
    mySocket.EndReceive(ar);
    lastRxTime = DateTime.Now;
    ...
}
Run Code Online (Sandbox Code Playgroud)

检查流程

void CheckConnection() {
    TimeSpan ts = DateTime.Now.Subtract(lastRxTime);
    if(ts.TotalMilliseconds > timeout) {
        Disconnect(string.Format("No packet received from the server for over {0} seconds.", timeout / 1000));
    }
}
Run Code Online (Sandbox Code Playgroud)

在问题发生期间我有有效的Wireshark捕获,在断开连接之前我看到NTP流量最终看起来像是至少1分钟的修正.这显然会导致检查过程失败.

技术细节/预期问题的答案

  1. 我可以控制连接的两端,但不能控制它们之间的物理层(通常是低质量的卫星链路),这就是为什么要进行超时检查的原因.
  2. 由于数据是异步的,因此如果没有数据从服务器发送一段时间等于超时的一半,则可以发送一个小的心跳.
  3. 此过程可以有多个实例(即在连接到多个不同服务器的计算机上).
  4. 所有通信都使用异步方法(据称使用完成端口).
  5. 检查过程在单个线程上运行,该线程由单个计算机上的所有客户端共享.

完成研究(即可能的解决方案)

我的谷歌搜索到目前为止导致以下结果:

  1. 我意识到我应该使用DateTime.UtcNow而不是DateTime.Now出于性能原因.这不会影响问题本身.
  2. 依赖于Ticks的实现将是更好的解决方案.
  3. 获得滴答有两种选择 - Environment.TickCountStopwatch.GetTimestamp()
  4. 根据我的研究,Environment.TickCount可能会受到时间调整的影响,但我不确定在什么情况下.此外,由于我在其他更高性能的情况下使用相同的方法,10-16毫秒的分辨率可能是一个问题(虽然不是我在这里提出的具体情况).
  5. 当高性能时钟不可用时,Stopwatch.GetTimestamp()可以回退DateTime.Now.Ticks.我不确定这种情况会发生多久(任何机器都不再配备高性能时钟),但我确信如果它转向Ticks会出现同样的问题.
  6. 我还读过Stopwatch.GetTimestamp()将使用QueryPerformanceCounter()API调用,并且从多个线程调用时可能会不稳定.

终极问题

我很好奇生成lastRxTime时间戳的最佳方法是什么?我是否过分担心 …

c# datetime

26
推荐指数
1
解决办法
1224
查看次数

标签 统计

c# ×1

datetime ×1