Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Task, qui es-tu ? partie 6

L’étude des propriétés de Task nous permet progressivement d’en comprendre les subtilités de fonctionnement. Continuons la série.

Liens rapides vers la série complète

L’ID de la tâche

La propriété Id de type integer permet de connaître l’identificateur qui a été attribué à la tâche. C’est pratique en débogue pour pister les messages émis par la tâches 3 et ceux de la tâche 22 en sachant quel code à émis quoi dans le fichier de Log par exemple.

Mais contrairement à ce qu’on croit et même à ce que la documentation semble indiquer, l’ID n’est pas unique. Il l’est “presque” mais pas tout à fait. Ce dont on est sur c’est qu’il ne peut pas prendre la valeur zéro.

Ce qu’il faut en retenir c’est qu’il ne faut pas utiliser cet ID autrement que pour le debug. On pourrait être tenté par exemple d’associer l’ID via un dictionnaire à des données relatives à une tâche. Ce serait une erreur car l’unicité n’est pas garantie et cela pourrait créer des conditions de bogues particulièrement redoutables à déminer ! Il existe d’autres moyens (un peu plus sophistiqués) pour ce genre de choses. Leur étude dépasse le cadre de cette série sur Task mais j’y reviendrais car c’est intéressant.

L’ID courant

Si l’ID de la tâche n’a d’intérêt qu’en débogue que dire de ce qui apparait comme un doublon qu’est CurrentId ?

Propriété de type integer aussi avec une variante, elle est nullable.

En réalité l’astuce est dans la définition : cette propriété retourne l’ID si la tâche existe et s’exécute et null dans les autres cas… Et cela ne fonctionne qu’avec les Task qui font tourner du code sinon il n’y a pas d’exécution de quoi que ce soit et pas d’ID ni de CurrentId (donc uniquement dans le cas des Delegate Tasks, pas les Promise Tasks).

Unicité ou pas ?

Le CurrentId pourrait être utilisé comme un ID unique alors que l’ID ne le peut pas alors même que le CurrentId retourne l’ID… Well… il y a un truc qui cloche !

Oui et non.

Il faut comprendre les ID sont générés “à la demande” par type. La première Task aura l’ID 1, le premier scheduler aura aussi un ID à 1. Et qui plus est la séquence qui attribue les ID semble avoir un petit problème. Car bien que la documentation dise que l’ID est unique, on peut trouver des codes de démo qui arrivent à générer des doublons au bout de quelques minutes.

J’ai testé l’un de ces codes (ci-dessous) et en moins de 3 minutes le programme avait trouvé un doublon. Je ne suis pas convaincu qu’il s’agisse d’une erreur dans le Framework. A mon sens il s’agit d’un problème d’interprétation quant à la notion d’unicité concernant une tâche.

Les tâches qui s’exécutent doivent avoir un ID unique. Celles qui ne sont plus exécutées n’ont plus d’intérêt et leur code peut être réutilisé. Dans ce cas la documentation serait exacte (les code sont unique, pour les tâches qui tournent) et les contradicteurs auraient aussi raison (l’unicité n’est pas absolue dans le temps si on prend en compte les tâches terminées).

using System;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        var task = new TaskCompletionSource<object>(null).Task;
        var taskId = task.Id;

        Task other;
        do
        {
            other = new TaskCompletionSource<object>(null).Task;
            if (other.Id == 0)
                Console.WriteLine("Saw Id of 0!");
        } while (other.Id != task.Id);

       Console.WriteLine("Id collision!");
       Console.WriteLine("  task.Id == other.Id: " + (task.Id == other.Id));
       Console.WriteLine("  task == other: " + (task == other));
       Console.ReadKey();
    }
}

Conclusion

Les ID ne sont pas les propriétés les plus intéressantes de Task mais ils recèlent des particularités étranges et des spécificités qu’il est bon de connaitre pour ne pas se fourvoyer…

Dans la prochaine partie nous allons voir comment on attend qu’une tâche se termine…

Stay Tuned !

blog comments powered by Disqus