Actualmente estoy trabajando en una aplicación principalmente asincrónica que utiliza TAP en todo momento. Cada clase que tiene métodos para generar Task
s también tiene un TaskScheduler
inyectado en él. Esto nos permite realizar una programación explícita de tareas, que según tengo entendido, no es la forma en que Microsoft utiliza el CTP Async.Async CTP: enfoque recomendado para la programación de tareas
El único problema que tengo con el nuevo enfoque (programación implícita) es que nuestra filosofía anterior siempre ha sido "sabemos que la continuación siempre especificará su programador de tareas, por lo que no tenemos que preocuparnos sobre qué contexto completamos la tarea en ".
Alejarse de eso nos preocupa un poco solo porque ha funcionado muy bien en términos de evitar errores sutiles de subprocesamiento, porque por cada bit de código podemos ver que el codificador se ha acordado de considerar en qué hilo está. Si se olvidaron de especificar el programador de tareas, es un error.
Pregunta 1: ¿Alguien me puede asegurar que el enfoque implícito es una buena idea? Veo tantos problemas que presenta ConfigureAwait (falso) y la programación explícita en el código heredado/de terceros. ¿Cómo puedo estar seguro de que mi código 'aguardado' siempre se ejecuta en el hilo de la interfaz de usuario, por ejemplo?
Pregunta 2: Así, suponiendo que quita todos los TaskScheduler
DI de nuestro código y comenzar a utilizar la programación implícita, ¿cómo después fijar el programador de tareas por defecto? ¿Qué hay de cambiar el programador a medio camino a través de un método, justo antes de esperar un método costoso, y luego volver a configurarlo de nuevo después?
(P. S. Ya he leído http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/configuring-waiting.aspx)
Gran respuesta Stephen, pero para aclarar: si ConfigureAwait (falso) fuera utilizado internamente por el método asíncrono 'A', ¿en qué contexto esperaría estar si esperaba el método 'A'? The threadpool, ¿o resumiría el contexto original antes de realizar una llamada esperada al método 'A'? –
La respuesta de Stephen es bastante sólida. Tenga en cuenta que si está configurado como inactivo en su modelo anterior, siempre puede crear un envoltorio personalizado que se pueda esperar (de forma similar a cómo funciona ConfigureAwait()) y engancharlo como un método de extensión en Tarea/Tarea. Por ejemplo, si su método de extensión se llamó ResumeOn (TaskScheduler ts), entonces el código podría verse así: espera Foo (...). ResumeOn (ts); Y luego tienen la misma semántica de programación que su propio código, pero con todas las bondades mejoradas de flujo/ejecución que 'aguardan'. –
@Lawrence: cada "capa" de métodos asíncronos pasa su contexto hacia abajo, pero no hacia arriba. Entonces, si 'A' llama' ConfigureAwait (false) ', terminará ejecutándose en el grupo de subprocesos. Entonces, cuando 'B' llama' await A() ', entonces' B' se reanudará en * su propio * contexto original después de 'await'. El hecho de que 'A' termine en el grupo de subprocesos no tiene efecto en el resto de' B'. –