A raíz de mi pregunta BeginInvoke()/EndInvoke(), hay diferencias importantes en el rendimiento/cualquier otra cosa entre Delegate. BeginInvoke() y el uso de QueueUserWorkItem() para invocar a un delegado de forma asincrónica?Cuál es la diferencia entre QueueUserWorkItem() y BeginInvoke(), para realizar una actividad asincrónica sin tipos de devolución necesarios
Respuesta
http://blogs.msdn.com/cbrumme/archive/2003/07/14/51495.aspx
dice:
"Un hecho sorprendente es que esta es también la razón por Delegate.BeginInvoke/ EndInvoke son tan lentos en comparación con técnicas equivalentes como ThreadPool.QueueUserWorkItem (o UnsafeQueueUserWorkItem si entiende las implicaciones de seguridad y desea ser realmente eficiente). La ruta de código para BeginInv oke/EndInvoke se convierte rápidamente en el código de procesamiento común de mensaje de la ruta de acceso remoto general. "
Hmmm, gracias, eso es interesante y atemorizante. ¡Creo que revertiré cualquier código de BeginInvoke()/EndInvoke() que no requiera valores devueltos! – endian
Lo principal que ocurre con QueueUserWorkItem
es que usted tiene que utilizar el tipo WaitCallback
delegado, que se ve complicado si ya tiene una instancia SomeRandomDelegate
y algunos argumentos. La buena noticia es que se puede solucionar este problema con un cierre:
ThreadPool.QueueUserWorkItem(
delegate { someDelegate(arg1, arg2); }
);
Este patrón también se asegura de que obtiene la tipificación fuerte adecuada en tiempo de compilación (a diferencia de pasar un arg object
estado para QueueUserWorkItem
y echándola en el método de destino). Este patrón también se puede utilizar cuando se llama a métodos directamente:
ThreadPool.QueueUserWorkItem(
delegate { SomeMethod(arg1, arg2); }
);
Obviamente, sin un equivalente EndInvoke
, tampoco se puede obtener un valor de retorno de vuelta a menos que se llama a un método/provocar un evento/etc al final de su método ... en una nota relacionada, debe tener cuidado con exception handling.
Al encontrar este escenario exacto, fue la primera vez que pensé para mis adentros: "Guau, me encanta". cierres ". –
Guau, este es un consejo supremo. Se siente como una semántica de boxeo/unboxing, y me imagino que no será más costoso, en un amplio esquema de cosas. –
Vaya, técnicamente, debería ser "delegar (objeto o)" o similar para que el código compile, creo, ya que QueueUserWorkItem espera una firma delegada que coincida con WaitCallback, es decir, una que incluya un solo parámetro de tipo objeto. –
No debería haber ninguna gran diferencia, también creo que el BeginInvoke/EndInvoke generado para un delegado usa el grupo de subprocesos para ejecutar.
No debería haber ninguna diferencia de rendimiento, ya que Delegate.BeginInvoke y ThreadPool.QueueUserWorkItem se ejecutarán en una cadena de subprocesos.
La mayor diferencia es que si llamas a BeginInvoke, estás obligado a llamar a EndInvoke en algún momento. Por el contrario, ThreadPool.QueueUserWorkItem es "disparar y olvidar". Eso tiene beneficios y desventajas. El beneficio es que puedes olvidarte de eso. El inconveniente es que no tiene forma de saberlo, a menos que agregue su propio mecanismo de sincronización/notificación, cuando la tarea se haya completado.
El EndInvoke() tiene un comportamiento útil, pero rara vez se menciona - es relanzamientos todas las excepciones no controladas que el delegado generado en el contexto del hilo original para que pueda mover la lógica de procesamiento de excepciones en el código principal.
Además, si su delegado tiene parámetros out/ref, se agregarán a la firma EndInvoke() permitiéndole obtenerlos cuando el método termine la ejecución.
muchas gracias, no sabía eso – endian
Si llama a ThreadPool.QueueUserWorkItem, las excepciones planteadas en el elemento de trabajo no se manejarán en el hilo de fondo (a menos que las capture explícitamente). En .Net 2 y superior esto terminará su AppDomain.
Si llama a delegate.BeginInvoke(), las excepciones se ponen en cola para volver a lanzarse cuando se llama a EndInvoke(). Si nunca llama a EndInvoke(), entonces las excepciones son esencialmente memoria 'filtrada' (como cualquier otro estado no liberado por la operación asincrónica).
- 1. ¿Cuál es la diferencia entre Invoke() y BeginInvoke()
- 2. Diferencia entre BeginInvoke y Thread.Start
- 3. ¿Cuál es la diferencia entre LOAD_DEFAULT y LOAD_NORMAL para WebSettings?
- 4. ¿Cuál es la diferencia entre invocar y BeginInvoking a MessageBox?
- 5. ¿Cuál es la diferencia entre getResourceAsStream con y sin getClassLoader?
- 6. ¿Cuál es la diferencia entre ssize_t y ptrdiff_t?
- 7. ¿Cuál es la diferencia entre `##` y `hashCode`?
- 8. ¿Cuál es la diferencia entre [indefinido] y [,]?
- 9. Cuál es la diferencia entre $ y jQuery
- 10. Devolución de llamada asincrónica en diagramas de actividad UML
- 11. ¿Cuál es la diferencia entre ".equals" y "=="?
- 12. Cuál es la diferencia entre = y: =
- 13. ¿Cuál es la diferencia entre dict() y {}?
- 14. ¿Cuál es la diferencia entre {0} y ""?
- 15. ¿Cuál es la diferencia entre .ToString (+) y ""
- 16. ¿Cuál es la diferencia entre una subrutina y una función?
- 17. ¿cuál es la diferencia entre una clase y una biblioteca?
- 18. ¿Cuál es la diferencia entre "$^N" y "$ +"?
- 19. ¿cuál es la diferencia entre:.! y: r !?
- 20. Cuál es la diferencia entre $ (...) y `...`
- 21. ¿Cuál es la diferencia entre + = y = +?
- 22. ¿Cuál es la diferencia entre " " y ""?
- 23. Realizar llamadas sin actividad ACTION_CALL
- 24. ¿Cuál es la diferencia entre una vista y una secuencia?
- 25. ARM: ¿Cuál es la diferencia entre APCS y AAPCS ABI?
- 26. ¿Cuál es la diferencia entre una sesión y una cookie?
- 27. Devolución de llamada asincrónica
- 28. ¿Cuál es la diferencia entre la vinculación estática y dinámica?
- 29. ¿Cuál es la diferencia entre pánico y una afirmación?
- 30. Diferencia entre Actividad y FragmentActivity
Es posible que también quiera ver: http://marcgravell.blogspot.com/2009/02/async-without-pain.html –