WinForms 应用程序表单在播放音频时“晃动”

Posted

技术标签:

【中文标题】WinForms 应用程序表单在播放音频时“晃动”【英文标题】:WinForms Application Form "Shakes" When Audio Playing 【发布时间】:2010-03-24 19:05:37 【问题描述】:

我正在开发一个 C# 游戏程序。它使用声音样本和winsock。

当我测试运行游戏时,大部分音频都可以正常工作,但有时如果顺序播放多个样本,应用程序表单会稍微晃动,然后回到原来的位置。

我该如何进行调试或以易于管理的方式将其呈现给你们?我敢肯定没有人会因为害怕病毒攻击而想要整个应用程序代码。

请指导我..

编辑:我无法确定任何产生此结果的代码部分。它就是这样,我无法解释。

编辑:不,x/y 位置没有改变。窗口像晃动了几个像素,然后又回到了晃动之前的位置。

if (audio)

    Stream stream;
    SoundPlayer player;

    stream = Properties.Resources.ResourceManager.GetStream("_home");
    player = new System.Media.SoundPlayer(stream);
    player.PlaySync();
    player.Dispose();

    string ShipID = fireResult.DestroyedShipType.ToString();
    stream = Properties.Resources.ResourceManager.GetStream("_" + ShipID);
    player = new System.Media.SoundPlayer(stream);
    player.PlaySync();
    player.Dispose();

    stream = Properties.Resources.ResourceManager.GetStream("_destroyed");
    player = new System.Media.SoundPlayer(stream);
    player.PlaySync();
    player.Dispose();

你能在上面的代码中看到任何会产生这种震动的东西吗?

编辑:是的,代码正在执行中: this.Invoke(new Action(delegate() ....));会是这样吗?我该如何解决?

编辑:

           stream = Properties.Resources.ResourceManager.GetStream("_destroyed");
           player = new System.Media.SoundPlayer(stream);
           player.PlaySync();
           player.Dispose();
           stream.Dispose();

如果去掉上面的代码,那么它就可以正常工作了!有什么想法吗?

编辑:我将这一行替换为:

stream = Properties.Resources.ResourceManager.GetStream("_destroyed");

换一个不同的文件名,但问题仍然存在,但至少不是音频文件损坏。

编辑:当有人发送微动时的 MSN?有点像,但只会发生 2 或 3 次。

编辑:您是否使用任何 3rd 方库? - 不,我没有使用任何 3rd 方库。

编辑:似乎不管是什么文件,第三个样本总是会导致这个。

编辑:在我使用声音样本的任何地方都会发生。如果我播放 3 个样本,情况就会发生。

编辑:@nobugz:是的认为你是对的。问题是等待 UI 线程的时间过长。正如我尝试使用合并的音频文件一样,问题在于它的原始持续时间。

编辑:我通过在每个示例播放命令后添加 Application.DoEvents(); 解决了这个问题。没有震动:)

编辑:上述解决方案并没有真正起作用。随着播放器样本数量的增加,应用程序 GUI 再次卡住。而是采用了使用 QueueUserWorkItem 的解决方案。这仍然有待证明是一种令人满意的解决方案,因为发生了交叉处理,即可以在旧样本仍在播放的同时启动新的样本线程。

随着更多知识的曝光,将对此进行更新。

【问题讨论】:

创建重现问题的最小示例程序,然后在此处询问示例,并根据需要发布尽可能多的代码。这也将帮助您进行调试。 你能把它发生的时间和你可以发布的一段代码隔离开来吗? 等等,窗口的 X/Y 位置正在改变? 可能是声音播放器干扰了 UI 线程中的某些东西吗?或者这是否已经在不同的线程中运行?另外,当你说摇一摇的时候,它是不是类似于 MSN 在某人发送轻推时的行为? (只是为了了解您所看到的情况) @Edit: 好的,所以窗口似乎在屏幕上移动了?我很困惑。 【参考方案1】:

在 UI 线程上调用 PlaySync 不是很好。当您的 UI 线程忙于等待声音结束时,它会使您的主窗口无响应,它不会像应该做的那样发送消息。如果这需要足够长的时间,Windows 会介入并用“幽灵”覆盖窗口,它通常会在标题栏中显示“无响应”(如果有的话)。这个幽灵窗口可能与您自己的窗口不太匹配,这可以解释“抖动”。

使用 Play() 可以解决这个问题。但是给你一个新的,排序声音变得困难。从线程进行调用可以解决这两个问题。查看NAudio 以更好地控制声音。

【讨论】:

我在想这可能与它有关(从 UI 线程中调用 PlaySync) - 如果确实发生了这种情况。但我不知道重影行为,尽管这解释了很多。这就是为什么我问它是否在 UI 线程中运行,因为我知道这会导致一些问题。 @nobugz:(从线程调用可以解决这两个问题)。您能否提及与您所说的内容相关的网络文章?看着 NAudio :) @nobugz:我会接受你的提示作为答案,因为它让我想到了我开发的解决方案。问候和感谢。 @ikurtz:fwiw,DoEvents() 并不是一个很好的解决方案。尝试在播放声音时关闭窗口。 @nobugz:如果我在播放声音时尝试关闭窗口,它会等到样本播放完毕。这是可以的行为。除非你有别的想法?我同意这是一个简化的解决方案,就好像样本比现在长我会再次遇到同样的问题。【参考方案2】:

复制您的程序。从副本中删除尽可能多的游戏元素。移除模块、删减游戏逻辑、在类之间转移函数以减少抽象(以便您可以删除类),并且通常会破坏游戏。

每次执行此操作时,请检查错误是否仍然存在。最初您将删除较大的程序块,但随着时间的推移,删除量会减少。

如果您发现某些内容在删除后修复了该错误,则有两种可能性:您找到了该错误,或​​者与程序的其余部分存在某种协同作用导致了该错误。在后一种情况下,继续删除更多的程序。

最终,您将得到一个有错误的最小程序。把它贴在这里(如果它太大的话,也可以放在一个粘贴箱里)。

这是我遇到根本无法定位的错误时使用的最后手段之一。

【讨论】:

好提示。我很高兴我能够在不极端的情况下隔离原因/代码。

以上是关于WinForms 应用程序表单在播放音频时“晃动”的主要内容,如果未能解决你的问题,请参考以下文章

调试模式下的directx音频视频错误消息

在设计器中为 winforms 应用程序打开的表单的运行上下文是啥

在Javascript中播放音频时出现意外行为

重命名 WinForms 表单的标题

当应用程序在后台时,我可以开始播放音频吗

当另一个应用开始播放音频时,如何自动暂停我的应用中的音频播放器?