without method await async c# async-await synchronizationcontext

c# - method - ¿Cómo obtener una tarea que utiliza SynchronizationContext? ¿Y cómo se usa SynchronizationContext de todos modos?



call async method c# await (2)

¿Cómo puedo obtener una Tarea, que realmente ejecuta una acción pero que se envía usando SynchronizationContext.Current.Send / Post?

Use el programador de tareas especiales:

Task.Factory.StartNew( () => {}, // this will use current synchronization context CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());

¿Y alguien puede recomendar una buena introducción a SynchronizationContext?

Mira el artículo It''s All About SynchronizationContext por Stephen Cleary.

Todavía estoy aprendiendo todo el concepto de tarea y TPL. Desde mi comprensión actual, las funciones de SincronizaciónContexto (si están presentes) se usan await para despachar la Tarea "en algún lugar". Por otro lado, las funciones en la clase Task no usan el contexto, ¿verdad?

Entonces, por ejemplo, Task.Run(...) siempre distribuirá la acción en un subproceso de trabajo del grupo de subprocesos e ignorará por completo SynchronizationContext.Current . await Foobar() usaría el contexto para ejecutar la tarea generada después de await ?

Si eso es cierto, mi pregunta es: ¿Cómo puedo obtener una Task , que realmente ejecuta una acción pero se envía usando SynchronizationContext.Current.Send/Post ?

¿Y alguien puede recomendar una buena introducción a SynchronizationContext , especialmente cuándo y cómo son utilizados por el resto del framework? MSDN parece ser muy callado sobre la clase. Los principales éxitos de Google ( aquí y aquí ) parecen estar diseñados solo para el envío de Windows Forms. Stephen Cleary escribió un artículo que es bueno para aprender qué contextos ya existen y cómo funcionan, pero me falta entender dónde y cuándo se usan realmente.


A medida que aprende esto, es importante señalar que la Task utilizada por el TPL es bastante diferente de la Task utilizada por async / await , aunque son del mismo tipo. Por ejemplo, TPL comúnmente usa tareas padre / hijo, pero async / await no.

TPL usa planificadores de tareas para ejecutar sus tareas. Como señaló Dennis, TaskScheduler.FromCurrentSynchronizationContext le proporcionará un programador de tareas que utiliza Post en el SynchronizationContext actual para ejecutar su tarea.

async / await generalmente no usa planificadores de tareas. Tengo una publicación introductoria de async / await en mi blog que incluye información de contexto, y también la menciono brevemente en mi artículo de MSDN (aunque es fácil pasarla por alto). Esencialmente, cuando un método async se suspende a la await , de forma predeterminada capturará el actual SynchronizationContext (a menos que sea null , en cuyo caso capturará el TaskScheduler actual). Cuando se reanuda el método async , se reanuda la ejecución en ese contexto.

Dennis señaló la forma TPL de programar una tarea para el actual SynchronizationContext , pero en el mundo async / await , ese enfoque no es necesario. Más bien, puede programar tareas explícitamente en el grupo de subprocesos a través de Task.Run :

async Task MyMethodAsync() { // Whee, on a SynchronizationContext here! await Task.Run(() => { }); // Ooo, on the thread pool! // Back on the SynchronizationContext ... // ... automagically! }

Escribí mi artículo SynchronizationContext precisamente porque faltaban los documentos de MSDN. Tengo un poco más de información en mi blog , pero todos los bits importantes están en el artículo de MSDN. Muchos tipos usan AsyncOperation lugar de SynchronizationContext directamente; la mejor documentación para esto está enterrada bajo los documentos de EAP (sección "Enhebrado y contexto") . Pero también debo señalar que EAP está efectivamente obsoleto debido a async / await , por lo que no escribiría código usando AsyncOperation (o SynchronizationContext ), a menos que estuviera escribiendo mi propio SynchronizationContext .