Tengo un motor de código que reproduce archivos WAV largos al reproducir trozos más pequeños en sucesión utilizando los métodos de API waveOutOpen y waveOutWrite. Para actualizar mi UI a medida que se reproduce el archivo, desde la función de devolución de llamada a medida que cada búfer termina de reproducirse, invoco un hilo separado (porque desea hacer lo mínimo posible dentro de la función de devolución de llamada) que llama a un método en mi forma.¿Cuánto dura el retraso entre Control.Invoke() y la llamada de su delegado?
El formulario contiene un nivel de clase EventHandler
que maneja un método dentro del cual actualizo elementos de IU con nueva información. En el método de formulario se llama desde la función de devolución de llamada waveOutWrite, utilizo el método de invocación de este modo:
if (_updatedisplay == null)
{
// UpdateDisplay contains code to set control properties on the form
_updatedisplay = new EventHandler(UpdateDisplay);
}
Invoke(_updatedisplay);
Everythings funciona, pero parece que de vez en cuando hay un retraso notable o el retraso en la actualización de la interfaz de usuario elementos. Esto es fácil de ver porque estoy usando el método UpdateDisplay para conducir una animación, por lo que los retrasos aparecen como "hipo", donde el elemento aparece congelado por una fracción de segundo antes de que salte a su posición esperada.
¿Es posible que exista a veces un retardo largo (tal vez 10-15 milisegundos) en una comunicación cruzada como esta? Si es así, ¿cuál es una mejor manera de manejar algo como esto?
actualización: por cierto, yo soy definitivamente no seguro de que Invoke
es el culpable aquí. Otra posibilidad es un retraso entre el momento en que un fragmento de audio termina de reproducirse y el momento en que se llama a la función de devolución de llamada.
Actualización 2: por itowlson
's sugerencia, he usado un System.Diagnostics.Stopwatch
para comparar el desfase entre Invoke
y llamada al método. De 1156 mediciones, obtuve 1146 a 0 ms, 8 a 1 ms y 2 a 2 ms. Creo que es seguro decir Invoke
no es mi culpable aquí.
Solo traté de usar BeginInvoke, pero sigue siendo hipo. Además, tengo el mismo problema hace un tiempo tratando de ejecutar una animación con devoluciones de llamada de un temporizador de alta resolución, y tengo el mismo tipo de fallas. Me pregunto si esto es algo fundamental con las UI de .Net. – MusiGenesis
No, es fundamental para * cualquier * UI al menos en lo que respecta a Windows. La arquitectura de mensajes en Windows Forms no es nada nuevo, es lo mismo que funciona una aplicación C++ en Windows.Si intentas actualizar una barra de progreso o algo así, no deberías invocar a través de los hilos. En su lugar, utilice escrituras interconectadas en una variable de progreso que el hilo de la interfaz de usuario lee en ciertos intervalos. – Josh
Esto * suena * como * tal vez * el componente de animación no es un buen ciudadano en términos de mensajes de bombeo, pero dudo en especular acerca de lo que está sucediendo aquí, especialmente porque no está seguro de que Invoke sea el problema. Intente capturar el momento en que se invocó BeginInvoke y cuando se inició la ejecución de UpdateDisplay: eso podría ayudar a identificar si el invocación de hilos cruzados es realmente el problema. (Necesitarás usar tiempos de alta resolución.) – itowlson