7

我正在用 C# 编写一个 UDP 多播客户端/服务器对,我需要大约 50-100 微秒(微秒)的延迟来限制服务器传输速率。这有助于避免严重的数据包丢失,也有助于防止受磁盘 I/O 限制的客户端过载。请不要建议使用 Thread.Sleep 或 Thread.SpinWait。我不会问我是否需要其中任何一个。

我的第一个想法是使用某种高性能计数器并执行一个简单的 while() 循环检查经过的时间,但我想避免这种情况,因为它感觉很笨拙。这不会也与服务器进程的 CPU 利用率挂钩吗?

跨平台解决方案的奖励积分,即不是特定于 Windows 的。提前谢谢各位!

4

6 回答 6

9

非常短的睡眠时间通常最好通过 CPU 旋转循环(如您描述的那种)来实现。您通常希望避免使用高精度计时器调用,因为它们本身会占用时间并扭曲结果。对于如此短的等待时间,我不会太担心服务器上的 CPU 挂钩。

我会将行为封装在一个类中,如下所示:

  • 创建一个类,它的静态构造函数运行一个自旋循环数百万次迭代并捕获它需要多长时间。这让您了解单个循环周期在底层硬件上需要多长时间。
  • 计算可用于计算任意睡眠时间的 uS/迭代值。
  • 当被要求休眠特定时间段时,将 uS 除以之前计算的 uS/迭代值,以确定要执行多少次循环迭代。
  • 使用 while 循环旋转,直到估计的时间过去。
于 2009-10-27T15:20:07.357 回答
7

我会使用秒表,但需要一个循环

阅读内容以向秒表添加更多扩展,例如 ElapsedMicroseconds

或者类似的东西也可能有用

System.Diagnostics.Stopwatch.IsHighResolution必须为真

    static void Main(string[] args)
    {
        Stopwatch sw;
        sw = Stopwatch.StartNew();
        int i = 0;

        while (sw.ElapsedMilliseconds <= 5000)
        {
            if (sw.Elapsed.Ticks % 100 == 0)
            { i++; /* do something*/ }
        }
        sw.Stop();


    }
于 2009-10-27T15:20:00.853 回答
1

当我需要更精确的多播应用程序时,我就遇到过这样的要求。

我发现最好的解决方案是使用多媒体计时器,如本例所示

我已经使用了这个实现并向它添加了 TPL 异步调用。您应该查看我的SimpleMulticastAnalyzer项目以获取更多信息。

于 2013-04-01T01:36:06.973 回答
1
    static void udelay(long us)
    {
        var sw = System.Diagnostics.Stopwatch.StartNew();
        long v = (us * System.Diagnostics.Stopwatch.Frequency )/ 1000000;
        while (sw.ElapsedTicks < v)
        {
        }
    }
    static void Main(string[] args)
    {
        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine("" + i + " " + DateTime.Now.Second + "." + DateTime.Now.Millisecond);
            udelay(1000000);
        }
    }
于 2016-10-22T22:06:37.220 回答
0

你看过多媒体计时器吗?您可能会在某处找到一个在某处包装 API 调用的 .NET 库。

于 2009-10-27T15:43:04.470 回答
0

我不鼓励使用自旋循环,因为它消耗并创建阻塞线程。thread.sleep 更好,它在睡眠期间不使用处理器资源,它只是切片时间。试试看,你会从任务管理器中看到 CPU 使用率是如何随着自旋循环而飙升的。

于 2013-03-08T13:07:07.163 回答