如何平均每20毫秒触发一个事件?内置定时器“蠕动”

本文关键字:事件 一个 内置 定时器 蠕动 何平 20毫 | 更新日期: 2023-09-27 18:13:56

我正在编写一个RTP服务器来发布PCMA波文件。它需要每20ms泵送一次数据(平均而言-对于任何一个泵,它可以在任何一边,但必须在20ms平均)。

我目前的实现使用了一个Timer,但是事件每隔20毫秒就会触发一次,所以它会逐渐消失。

有更好的方法吗?我目前能想到的唯一方法是在它开始爬行时动态调整计时器间隔,以便使其恢复正常。

void Main()
{
    System.Timers.Timer timer = new System.Timers.Timer();
    // Use a stopwatch to measure the "wall-clock" elapsed time.
    Stopwatch sw = new Stopwatch();
    sw.Start();
    timer.Elapsed += (sender, args) => 
    {
        Console.WriteLine(sw.ElapsedMilliseconds);
        // Simulate doing some work here - 
        // in real life this would be pumping data via UDP.
        Thread.Sleep(300);
    };
    timer.AutoReset = true;
    // I'm using an interval of 1 second here as it better 
    // illustrates the problem
    timer.Interval = 1000;
    timer.Start();
}
输出:

1002
2001
3002
4003
5003
6005
7006
8007
9007
10017
11018
12019
13019
14020 <-- By this point we have creeped over 20 ms in just 14 iterations :(

如何平均每20毫秒触发一个事件?内置定时器“蠕动”

首先:我永远不会得到它是准确的,因为你的程序永远不会完全控制CPU的正在做什么,只要你在标准的Windows上运行,因为它不是一个实时的操作系统。想想杀毒软件,垃圾收集器冻结你的线程,在旁边玩游戏,…

也就是说你可以补偿一点。

当处理程序启动时,暂停计时器,记录当前时间,行动,通过根据处理程序的开始和行动所花费的时间将间隔设置为所需的间隔来更新时间间隔。

这样你可以更好地控制爬行。但有一种例外情况,即行动时间长于间隔时间,以及间隔时间是否应包括行动时间或行动之间的时间。

根据我的经验,你不能依靠任何计时器来精确地获得那么小(20毫秒)的间隔,但补偿蠕变可以帮助很大。

你可以使用StopWatch来测量时间,但是它没有回调。

可以使用Windows多媒体定时器。它涉及一些WinAPI,但本文提供了所有细节。