2010-02-20 10 views
6

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í.

Respuesta

3

Sí, puede haber una demora arbitrariamente larga. Invocar funciona enviando un mensaje de Windows al control de destino, por lo que solo se procesará cuando el hilo de destino bombee mensajes. Si el hilo ya está procesando un mensaje, y ese proceso lleva tiempo, puede haber un retraso apreciable antes de que el hilo bombee su siguiente mensaje y, por lo tanto, procese la invocación.

Una mejor manera puede ser llamar a BeginInvoke. Esto no evita la posible demora en el subproceso de la interfaz de usuario que procesa el mensaje, pero evita que se bloquee su cadena de llamada mientras espera que el subproceso de la interfaz de usuario bombee mensajes. Sin embargo, esto puede no ser de ayuda en su escenario donde parece que es el ajetreo del subproceso de interfaz de usuario que está causando fallas en la animación.

actualización en respuesta a la actualización: Nota todo lo que estoy diciendo aquí es que hay podría haber un arbitrariamente larga demora, no es que no se ser un retraso notable o que este es sin duda la causa de tu retraso 10-15ms parece ser un tiempo inusualmente largo para que una aplicación gaste en el procesamiento de mensajes a menos que haya algo realmente intenso ocurriendo en el hilo de la interfaz de usuario, por lo que sin duda es prudente considerar causas alternativas.

+0

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

+2

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

+0

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

Cuestiones relacionadas