programming parallel new net library for examples c# multithreading task-parallel-library system.reactive conceptual

c# - parallel - ¿Cuál es la diferencia conceptual entre SynchronizationContext y TaskScheduler?



plinq c# (2)

Stephen Toub blogueó eso

Tanto SynchronizationContext como TaskScheduler son abstracciones que representan un "planificador", algo a lo que le da algo de trabajo, y determina cuándo y dónde ejecutar ese trabajo. Hay muchas formas diferentes de programadores. Por ejemplo, ThreadPool es un planificador: usted llama a ThreadPool.QueueUserWorkItem para proporcionar un delegado para ejecutar, ese delegado se pone en cola y uno de los hilos de ThreadPool finalmente recoge y ejecuta ese delegado. Su interfaz de usuario también tiene un programador: la bomba de mensajes.

Así que las implementaciones System.Reactive.Concurrency.EventLoopScheduler , Dispatcher , ThreadPool , TaskScheduler , SyncrhonizationContext e IScheduler de Reactive Extensions son todas "programadoras" en ese sentido.

¿Cuál es la diferencia entre ellos?

¿Por qué eran todos necesarios? Creo que tengo EventLoop, Dispatcher, ThreadPool. Ischeduler también están bien explicados.
Pero TaskScheduler y SyncrhonizationContext todavía no están claros para mí.

El excelente artículo de Stephen Cleary explica SyncrhonizationContext, y creo que lo entiendo. ¿Por qué entonces necesitamos TaskScheduler, no está claro.

Por favor explique o señale una fuente.


Aunque, como se cita,

Tanto SynchronizationContext como TaskScheduler son abstracciones que representan un "planificador"

OMI, el grado de abstracción (y por lo tanto API) difiere. SynchronizationContext es una API más genérica en el sentido de que Post / Send toma un método simple de delegado.

Por otro lado, TaskScheduler es una abstracción que es específica de TPL, por lo que ofrece métodos como QueueTask, que se ocupa del objeto Task . El uso del contexto de sincronización en lugar del programador de tareas (es decir, tener una implementación específica de TPL de SynchronizationContext) hubiera hecho que fuera más tedioso trabajar con la programación de tareas (y, por supuesto, sería una API de tipo débil en el contexto de TPL). Así que los diseñadores de TPL han optado por modelar una API de planificador abstracto que tenga sentido para TPL (de todos modos, ese es el propósito de la abstracción, ¿no?). Por supuesto, para cerrar la brecha, FCL contiene una clase interna SynchronizationContextTaskScheduler que es la implementación más simple de TaskScheduler sobre SynchronizationContext.

SynchronizationContext se introdujo en .NET 2.0 mientras que TPL se introdujo en .NET 4. Es interesante pensar qué habrían elegido los diseñadores de FCL si la secuencia fuera al revés, es decir, si TPL hubiera existido en el momento de .NET 2.0. OMI, TaskScheduler podría haber sido usado en lugar de SynchrinizationContext al modelar delgates como tarea en especialización específica.


Cada plataforma tiene su propio "programador" y tienen sus propias abstracciones a su alrededor. Por ejemplo, WinForms usa una bomba de mensajes. WPF usa otra bomba de mensajes resumida dentro de "Dispatcher". Un ThreadPool es otro "planificador" resumido dentro de "ThreadPool". Estos (y algunos otros) son programadores de nivel inferior.

Una Tarea y un Programador de Tareas desearían que el usuario de una Tarea no tenga que pensar en programar tareas en estos niveles más bajos (por supuesto, puede hacerlo de una manera abstracta). Debería poder iniciar una tarea y un "programador" de ambiente debería encargarse de ello. Por ejemplo, TaskFactory.StartNew(()=>{LengthyOperation()}) debería funcionar independientemente de la plataforma en la que esté ejecutando. Ahí es donde entra en juego SynchronizationContext . Conoce qué programadores de nivel inferior están involucrados en el marco que se ejecuta actualmente. Eso se pasa a un TaskScheduler y ese programador puede programar tareas (posiblemente en ThreadPool) y programar continuaciones a través del programador de nivel inferior asociado con el marco actualmente en ejecución (consulte SynchronizationContext ) para mantener los requisitos de sincronización. por ejemplo, aunque le gustaría que su tarea se ejecute en ThreadPool, es posible que desee una continuación para ejecutarse en el subproceso de la interfaz de usuario.

Es importante saber que el TaskScheduler es una abstracción de varios otros programadores. Esta no es la única razón por la que existe, sino una de las razones de esta "abstracción" adicional.