Depuis peu je suis de temps en temps questionné sur des petits soucis de programmation parallèle ou de gestion de Thread avec WF4. Pour commencer à répondre à ce genre de question il faut commencer par prendre WF4 à la base.

WF4 n’a pas :

  • De mécanisme de synchronisation de threads
  • De méthode pour invoquer des activités en mode asynchrone.
  • D’activité Parallel qui fasse du parallélisme de branche séquentielles sur plusieurs thread.

Pourquoi?

WF4 n’en a pas besoin, c’est tout…

En fait une instance de workflow s’exécute dans un seul Thread. A chaque fois que la méthode Schedule est appelées sur le contexte, une activité est programmée pour s’exécuter. Celle-ci s’exécutera en fonction de la disponibilité du Scheduler de l’instance de workflow qui exécutera l’activité et passera à la suite.

Seule exception à ce model, les activité héritant de AsyncCodeActivity et celles qui utilisent des Bookmarks.

En respectant cette logique on comprend plus aisément l’usage de l’activité Parallel : Celle ci ne permettra l’exécution de ses branche en parallèle, que si en sont sein sont glissées de branches utilisant des activités de type asynchrones. Hors de ce contexte, les branches s’exécuteront les unes à la suite des autres.

Pour illustrer clairement la chose, voici le code de la méthode Execute de la fameuse activité Parallel :

    protected override void Execute(NativeActivityContext context)
    {
        if ((this.branches != null) && (this.Branches.Count != 0))
        {
            CompletionCallback onCompleted = new CompletionCallback(this.OnBranchComplete);
            for (int i = this.Branches.Count - 1; i >= 0; i--)
            {
                context.ScheduleActivity(this.Branches[ i ], onCompleted);
            }
        }
    }

Quand on lit ces quelques lignes, au moins les choses sont claires. L’activité Parellel Schedule chacune de ses branches et c’est tout, il n’y a pas d’exécution via un Framework de parallélisme. Toute la notion de “parallélisme” est basée sur les activité asynchrones et non sur l’activité Parallel.

Dans WF4 il ne faut donc pas coder ses propres appels au pool de thread ou autre choses du genre pour exécuter une acticité. Si on le souhaite, on peut coder une activité avec des notions de parallélisme / multi-threading mais ce doit avoir lieu dans une AsyncCodeActivity.

Hors d’une AsyncCodeActivity, tout exécution prend la main sur le thread qui a invoqué le workflow. Ne soyez donc pas surpris si vous bloquez vos workflows en voulant exécuter des tâche de manière asynchrones dans une activités non asynchrones ;)

Mon poste sur les activités non bloquantes est une bonne illustration de ce type de cas : [WF4] Coder une activité d’attente non bloquante sans bookmark