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

Mus*_*sis 6 .net c# 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);
Run Code Online (Sandbox Code Playgroud)

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

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

更新:顺便说一下,我绝对相信Invoke是这里的罪魁祸首.另一种可能性是在一大块音频完成播放和实际调用回调函数之间存在滞后.

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

ito*_*son 3

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

更好的方法可能是调用 BeginInvoke。这并不能避免 UI 线程处理消息的潜在延迟,但它可以避免调用线程在等待 UI 线程泵送消息时被阻塞。但是,这在您的场景中可能没有帮助,听起来好像是 UI 线程的繁忙导致了动画中的故障。

根据您的更新进行更新: 请注意,我在这里所说的是可能存在任意长的延迟,而不是会有明显的延迟或这绝对是延迟的原因。对于应用程序来说,10-15 毫秒在消息处理上花费的时间确实异常长,除非 UI 线程上发生了非常密集的事情,所以考虑其他原因当然是明智之举!

  • 不,它是*任何* UI 的基础,至少就 Windows 而言是如此。Windows 窗体中的消息体系结构并不是什么新鲜事,甚至 C++ 应用程序在 Windows 中的工作方式也是如此。如果您尝试更新进度条或某些内容,则不应跨线程调用。而是使用对进度变量的互锁写入,UI 线程以一定的时间间隔读取该变量。 (2认同)