c# - 连续调用 Console.Beep() 之间的延迟

标签 c# .net

我正在尝试制作一个简单的程序来生成可根据输入值变化的音调。我想使用 Console.Beep() 函数,因为它似乎是最简单的解决方案,但遇到了问题。我注意到当我连续调用 Console.beep() 函数时,如下所示:

System.Console.Beep(440, 500);
System.Console.Beep(460, 500);
System.Console.Beep(480, 500);

当前音调停止和下一个音调开始之间有一个小的延迟(大约 100-200 毫秒左右)。我想知道是否有任何方法可以减少这种延迟,以便在频率更新时音调不会出现暂时停顿?

最佳答案

当试图理解为什么 .NET 以不受欢迎的方式运行时,在 GitHub 上查看 .NET Core 的源代码通常会很有帮助。看着the source code for Console.Beep :

    public static void Beep(int frequency, int duration)
    {
        ConsolePal.Beep(frequency, duration);
    }

ConsolePal 有两种实现方式:一种用于 Windows,另一种用于类 Unix 系统。假设您使用的是 Windows,让我们看一下 the Beep implementation in ConsolePal.Windows.cs :

    public static void Beep(int frequency, int duration)
    {
        const int MinBeepFrequency = 37;
        const int MaxBeepFrequency = 32767;

        if (frequency < MinBeepFrequency || frequency > MaxBeepFrequency)
            throw new ArgumentOutOfRangeException(nameof(frequency), frequency, SR.Format(SR.ArgumentOutOfRange_BeepFrequency, MinBeepFrequency, MaxBeepFrequency));
        if (duration <= 0)
            throw new ArgumentOutOfRangeException(nameof(duration), duration, SR.ArgumentOutOfRange_NeedPosNum);

        Interop.Kernel32.Beep(frequency, duration);
    }

这里的关键行是调用 Interop.Kernel32.Beep。这是一个强有力的指标,表明我们将调用 native Windows API,但让我们验证一下。 Interop.Kernel32split over a bunch of files --通常这可能会给我们带来一些困难,但碰巧列表中的第一个是 Interop.Beep.cs--方便!

打开文件,我们对原生调用的怀疑are confirmed :

    [DllImport(Libraries.Kernel32, SetLastError = true)]
    internal static extern bool Beep(int frequency, int duration);

这是使用一种称为平台调用的技术,通常缩写为 P/Invoke。有一个很棒的站点 pinvoke.net,它提供了常见的 P/Invoke 代码段以及一些附带的实现。让我们看看what pinvoke.net has to say about Beep in kernel32.dll :

Unlike MessageBeep, this function is synchronous. (It doesn’t return control to its caller until the sound finishes.)

由于您的代码或 Console.Beep 中没有任何其他内容会导致延迟,这意味着 Windows API 可能是罪魁祸首。幸运的是,pinvoke.net 提供了一种可能有效的解决方法。为了确定,让我们检查一下 MSDN's documentation on Windows' Beep , pinvoke.net 方便地链接到它。它附带了一些关于 Beep 的非常有趣的历史,以及切换到 MessageBeep 的建议。

不幸的是,the MSDN documentation for MessageBeep带来失望:我们不能用它来生成任意音调。

这使我们得出了最终结论:kernel32 的 Beep 并不是真正用于生成奇特的声音。它既依赖于硬件又依赖于平台,如果您试图在各种设备上生成一致的声音,那么这两者都不是理想的选择。它本质上是过去的遗物。它甚至在 Windows XP 中被删除,尽管它后来被添加回 Windows 7。这意味着 .NET 的 Console.Beep(int, int) 有所有相同的问题,因为它只是 kernel32 的包装器嘟嘟声

更可靠的解决方案是研究各种音频框架,但这些框架可能会复杂得多。现在,如果您刚刚开始使用 C# 并希望让事情变得简单,您可能会遇到不一致的情况,例如您观察到的延迟。

关于c# - 连续调用 Console.Beep() 之间的延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57650484/

相关文章:

c# - winform进度条运行期间执行代码

c# - 对 C# 哈希集进行切片

c# - 指定使用哪些 DNS 服务器来解析 .NET 中的主机名

c# - 如何检查容器中是否已存在 key ?

c# - 在 WPF 中使用图像和图标

c# - 将对象 [,] 转换为字符串 [,]

c# - 请求了错误的脚本 url

c# - 模拟从抽象类派生的抽象类

c# - Xml序列化-直接渲染Root下的对象列表-Xml-Element

c# - 从 LINQ 集合中删除项目