6

我有一个代码引擎,它通过使用 waveOutOpen 和 waveOutWrite API 方法连续播放较小的块来播放长 WAV 文件。为了在文件播放时更新我的​​ UI,在每个缓冲区完成播放时从回调函数中调用一个单独的线程(因为您希望在回调函数中尽可能少地执行操作),该线程在我的表单中调用一个方法。

该表单包含一个处理方法的类级别EventHandler,在该方法中我使用新信息更新 UI 元素。在从 waveOutWrite 回调函数调用的表单方法中,我使用 Invoke 方法,如下所示:

if (_updatedisplay == null)
{
    // UpdateDisplay contains code to set control properties on the form
    _updatedisplay = new EventHandler(UpdateDisplay);
}
Invoke(_updatedisplay);

一切正常,但似乎偶尔会在更新 UI 元素时出现明显的滞后或延迟。这很容易看出,因为我使用 UpdateDisplay 方法来驱动动画,因此延迟显示为“打嗝”,其中精灵在跳到预期位置之前似乎冻结了一瞬间。

像这样的跨线程通信有时是否可能存在很长的(可能是 10-15 毫秒)延迟?如果是这样,处理此类事情的更好方法是什么?

更新:顺便说一句,我绝对不确定Invoke是罪魁祸首。另一种可能性是一段音频完成播放和回调函数实际被调用之间的延迟。

更新 2:根据itowlson的建议,我使用 aSystem.Diagnostics.Stopwatch来衡量Invoke和方法调用之间的延迟。在 1156 次测量中,我在 0 毫秒时得到 1146 次,在 1 毫秒时得到 8 次,在 2 毫秒时得到 2 次。我认为可以肯定地说Invoke不是我的罪魁祸首。

4

1 回答 1

3

是的,可以有任意长的延迟。Invoke 通过向目标控件发送 Windows 消息来工作,因此它只会在目标线程泵送消息时得到处理。如果线程已经在处理一条消息,并且该处理需要时间,那么在线程泵送其下一条消息并因此处理 Invoke 之前可能会有明显的延迟。

更好的方法可能是调用 BeginInvoke。这并不能避免 UI 线程处理消息的潜在延迟,但它可以避免您的调用线程在等待 UI 线程发送消息时被阻塞。但是,这在您的场景中可能无济于事,因为它听起来像是 UI 线程的忙碌导致动画中出现故障。

更新以响应您的更新: 请注意,我在这里所说的只是可能会有任意长的延迟,而不是会有明显的延迟,或者这绝对是您延迟的原因。除非在 UI 线程上发生了真正密集的事情,否则 10 到 15 毫秒对于应用程序来说似乎是一个异常长的时间用于消息处理,因此考虑其他原因当然是明智的!

于 2010-02-20T21:51:26.070 回答