web-dev-qa-db-fra.com

Comment obtenir une tâche qui utilise SynchronizationContext? Et comment SynchronizationContext est-il utilisé de toute façon?

J'apprends toujours le concept de tâche et le TPL. D'après ma compréhension actuelle, les fonctions SynchronizationContext (si présentes) sont utilisées par await pour distribuer la tâche "quelque part". D'un autre côté, les fonctions de la classe Task n'utilisent pas le contexte, non?

Ainsi, par exemple, Task.Run(...) enverra toujours l'action sur un thread de travail du pool de threads et ignorera complètement le SynchronizationContext.Current. await Foobar() utiliserait le contexte pour exécuter la tâche générée après le await?

Si cela est vrai, ma question est: comment puis-je obtenir un Task, qui exécute réellement une action mais est distribué à l'aide de SynchronizationContext.Current.Send/Post?

Et quelqu'un peut-il recommander une bonne introduction à SynchronizationContext, en particulier quand et comment ils sont utilisés par le reste du framework? Le MSDN semble très calme sur la classe. Les meilleurs résultats Google ( ici et ici ) semblent être adaptés uniquement à la répartition des formulaires Windows. Stephen Cleary a écrit n article ce qui est bien d'apprendre quels contextes existent déjà et comment ils fonctionnent, mais je ne sais pas où et quand ils sont réellement utilisés.

26
Imi

Comment puis-je obtenir une tâche qui exécute réellement une action mais est distribuée à l'aide de SynchronizationContext.Current.Send/Post?

Utilisez un planificateur de tâches spécial:

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

Et quelqu'un peut-il recommander une bonne introduction à SynchronizationContext

Regardez l'article Il s'agit du SynchronizationContext de Stephen Cleary.

40
Dennis

Pendant que vous apprenez cela, il est important de souligner que Task tel qu'utilisé par le TPL est assez différent de Task tel qu'utilisé par async/wait , même s'ils sont du même type. Par exemple, TPL utilise généralement des tâches parent/enfant, mais pas async/await.

TPL utilise des planificateurs de tâches pour exécuter ses tâches. Comme l'a souligné Dennis, TaskScheduler.FromCurrentSynchronizationContext vous donnera un planificateur de tâches qui utilise Post sur le SynchronizationContext en cours pour exécuter sa tâche.

async/await n'utilise généralement pas de planificateurs de tâches. J'ai une introduction async/await post sur mon blog qui comprend des informations de contexte, et je le mentionne également brièvement dans mon article MSDN (c'est facile à oublier, cependant). Essentiellement, lorsqu'une méthode async se suspend à un await, par défaut, elle capturera le SynchronizationContext actuel (sauf s'il s'agit de null, auquel cas il capturer le TaskScheduler) actuel. Lorsque la méthode async reprend, elle reprend l'exécution dans ce contexte.

Dennis a souligné la manière TPL de planifier une tâche dans le monde actuel de SynchronizationContext, mais dans le monde async/await, cette approche n'est pas nécessaire. Vous pouvez plutôt planifier explicitement des tâches dans le pool de threads via Task.Run:

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

J'ai écrit mon SynchronizationContext article précisément parce que les documents MSDN manquaient tellement. J'ai un peu plus d'informations sur mon blog , mais tous les bits importants sont dans l'article MSDN. De nombreux types utilisent AsyncOperation plutôt que SynchronizationContext directement; la meilleure documentation pour cela est enterrée sous les documents EAP (section "Threading et Context") . Mais je dois également souligner que l'EAP est effectivement obsolète en raison de async/await, donc je n'écrirais pas de code en utilisant AsyncOperation (ou SynchronizationContext) - sauf si j'écrivais le mien SynchronizationContext.

26
Stephen Cleary