La Stream oubliée qui fait mal

Malheureusement dans le doux monde du développement d’application pour nos amis les serveurs, tout ne passe pas forcément par SQL ou WCF et il faut de temps en temps jouer des coudes avec nos amis les Stream.

Peu de personnes s’en souviennent, mais à l’époque de .net 1.0 (oui, pas 1.1) la Stream était une petite classe très sympathique pour les développeurs “tête en l’aire”. A partir du moment où l’on sortait de la porté de sa déclaration d’une stream, elle libérait les ressources associées (fichiers…). Le flush n’était pas toujours utilisé et le close pouvait être oublié… le rêve diront certain. Le fait est que cela fonctionnait bien sous NT4 et que je n’ai jamais bloqué un fichier ou un port TCP.

Depuis 1.1, les choses ont bien changé :

  • Le Flush n’est pas obligatoire, mais il est préférable de l’utiliser.
  • Le Close est “presque” obligatoire si on ne veut pas avoir des fichiers bloqués.
  • Le Dispose fait bien sont travail et l’oublié peut vous causer bien des tracas.

Avec .net 2 le “using” à bien changé la donne, et on en voit partout ou presque.

Malheureusement aujourd’hui je vois de plus en plus de cas où l’on oublie qu’une Stream est de la partie. Dernièrement je suis tombé sur un cas simple, où le code créé de nombreux fichiers vides de manière asynchrone et les supprime ultérieurement.

En soit, rien de bien tordu. Le développeur à utilisé intensivement la méthode Create de File.

String path ="chemin vers le fichier txt";
File.Create(path);

Mais les problèmes sont vite arrivés quand l’application est montée en charge : des fichiers étaient bloqués par un autre processus. Le souci n’avait pas pour origine les appels asynchrones à la méthode de création des fichiers, mais l’utilisation “inconsciente” de stream.

Et oui, File.Creat() créé une Stream et la retourne à l’utilisateur. Ensuite il faut penser à la fermer ;)

Dans se genre de cas, celà semble stupide de premier abord, mais le code suivant est des plus pratiques :

using (FileStream file = File.Create(path)) { }

Même si personnellement, en vieux casse-pied, je préférais ce code si :

FileStream file=null;
try
{
    // Création d'un fichier
    file = File.Create(path);
    // Fermeture du fichier
    file.Close();
}
finally
{
    // Libération des ressouces
    if (file != null)
    {
        file.Dispose();
        file = null;
    }
}

Mais ceci est une histoire de goûts.

Dans tous les cas, même si  vous n’utilisez jamais la Stream retournée par System.Io, penser toujours à la récupérer pour la fermer… vous gagnerez beaucoup de temps de débug ;)

Jérémy Jeanson

Comments

You have to be logged in to comment this post.