Control.Invoke()与其Delegate的调用之间有多长时间的延迟?

时间:2010-02-20 21:47:54

标签: c# .net multithreading waveoutwrite

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

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

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

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

这样的跨线程通信有时会出现很长(可能是10-15毫秒)的延迟吗?如果是这样,处理这样的事情的更好方法是什么?

更新:顺便说一句,我肯定确定Invoke是罪魁祸首。另一种可能性是在一大块音频完成播放和实际调用回调函数之间存在滞后。

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

1 个答案:

答案 0 :(得分:3)

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

更好的方法是调用BeginInvoke。这并不能避免处理消息的UI线程中的潜在延迟,但它会在等待UI线程抽取消息时保存您的调用线程。但是,这可能对您的场景没有帮助,因为它听起来像UI线程的忙碌导致动画中出现故障。

更新以响应您的更新:请注意,我在这里说的是可能是一个任意长的延迟,而不是将 em>明显延迟或者这绝对是导致您延误的原因。对于应用程序花费在消息处理上的10-15ms看起来似乎是非常长的时间,除非在UI线程上发生了非常密集的事情,所以你当然明智地考虑其他原因!