【问题标题】:Sending an audio packet every 20 milliseconds每 20 毫秒发送一个音频包
【发布时间】:2019-12-03 15:01:19
【问题描述】:

我有一个需要通过 UDP 发送音频数据包的应用程序。为了避免抖动,我想安排一个线程或任务每 20 毫秒执行一次此任务。伪代码如下所示:

while(true) 
{
    byte[] packet = GetNextPacket();
    socket.Send(packet);
    var waitUntill = DateTime.Now.AddMilliseconds(20);
    while(DateTime.Now < waitUntill) { }
}

这工作正常,但它使用了 100% 的 CPU 内核。这当然是不可取的。我尝试过使用 Thread.SleepThread.Yield 以及它们的任务等效项,但在所有情况下,我要么最终得到 100% 的负载,要么得到极度紧张的体验(这是意料之中的)。

在 C# 中没有办法在如此细粒度的级别上安排任务吗?我不需要 100% 的保证(Windows 不是实时操作系统),但大多数时候都可以使用。请注意,我并不担心 GC :)。

我可以调用任何 COM 代码来实现这一点,尽管我理想的解决方案是多平台的。我目前正在使用 dotnet core 3.0。

如果在 C# 中无法实现,那么如何在 C++ 等执行此类任务的语言中实现。

【问题讨论】:

  • 在异步方法await Task.Delay(20);
  • jitter的问题主要来自网络拥塞。您最好尝试在接收端稍微缓冲它。另外,请了解 UDP 会丢失数据报,您需要考虑丢失的数据。
  • 在这里使用异步回调将大大受益。它允许您将这些数据包信息与您的计算机执行的任何其他逻辑并行运行。
  • @Slothario 听起来不错! :D
  • @Slothario 您可以将您的评论转换为答案吗?因为它使用多媒体计时器就像一个魅力。不幸的是不是跨平台的,但我希望以后能解决这个问题。

标签: c# multithreading networking task scheduling


【解决方案1】:

研究使用多媒体计时器:

High resolution timer in C#

它们专为此类高分辨率应用而设计。

【讨论】:

    【解决方案2】:

    System.Threading.Timer 对象就是为这类事情而设计的,尽管我从未在如此短的时间间隔内使用过它。

    var timer = new Timer(_ => socket.Send(GetNextPacket()), null, 0, 20);
    

    【讨论】:

    • 感谢您的回答。我不确定这是否与普通 thread.sleep 有相同的抖动问题。明天一定会试试这个:D.
    • 不幸的是 System.Threading.Timer 与所有其他 Sleep 和 Delay 方法具有相同的精度。有关更多信息,请参阅此问题/答案:stackoverflow.com/questions/3744032/…
    • 您是否尝试过 Slothario 在对您的问题的评论中提到的多媒体计时器?
    猜你喜欢
    • 2011-04-23
    • 2015-11-28
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多