I have a code engine that plays long WAV files by playing smaller chunks in succession using the waveOutOpen and waveOutWrite API methods. In order to update my UI as the file plays, from the callback function as each buffer completes playing I Invoke a separate thread (because you want to do as little as possible inside the callback function) that calls a method in my form.
The form contains a class level EventHandler
that handles a method within which I update UI elements with new information. In the form method called from the waveOutWrite callback function, I use the Invoke method like so:
if (_updatedisplay == null)
{
// UpdateDisplay contains code to set control properties on the form
_updatedisplay = new EventHandler(UpdateDisplay);
}
Invoke(_updatedisplay);
Everythings works, but it appears that once in a while there is a noticeable lag or delay in the updating of the UI elements. This is easy to see because I am using the UpdateDisplay method to drive an animation, so the delays appear as "hiccups" where the sprite appears to freeze for a split second before it jumps to its expected position.
Is it possible that there is sometimes a long (maybe 10-15 milliseconds) delay involved in cross-thread communication like this? If so, what's a better way of handling something like this?
Update: by the way, I'm definitely not sure that Invoke
is the culprit here. Another possibility is a lag between when a chunk of audio finishes playing and when the callback function actually gets called.
Update 2: per itowlson
's suggestion, I used a System.Diagnostics.Stopwatch
to benchmark the lag between Invoke
and method call. Out of 1156 measurements, I got 1146 at 0ms, 8 at 1ms, and 2 at 2ms. I think it's safe to say Invoke
is not my culprit here.
Yes, there can be an arbitrarily long delay. Invoke works by sending a Windows message to the target control, so it will only get processed when the target thread pumps messages. If the thread is already processing a message, and that processing takes time, then there may be an appreciable delay before the thread pumps its next message and thereby processes the Invoke.
A better way may be to call BeginInvoke. This doesn't avoid the potential delay in the UI thread processing the message, but it saves your calling thread from being blocked while waiting for the UI thread to pump messages. However, this may not help in your scenario where it sounds like it's the busy-ness of the UI thread which is causing glitching in the animation.
Update in response to your update: Note all I'm saying here is that there could be an arbitrarily long delay, not that there will be a noticeable delay or that this is definitely the cause of your delay. 10-15ms does seem an unusually long time for an application to spend in message processing unless there's something really intensive happening on the UI thread, so you're certainly wise to consider alternative causes!