StreamWriter : Exception que je ne comprends pas...

StreamWriter : Exception que je ne comprends pas... - C#/.NET managed - Programmation

Marsh Posté le 03-11-2005 à 16:31:56    

Salut,
 
J'ai un programme en mode Console.
 
Dedans, j'ai une classe "logFile" dont voici le contruteur et la méthode qui pante :

Code :
  1. public logFile(string logName)
  2.  {
  3.   file = new StreamWriter(logName, true, System.Text.UTF8Encoding.UTF8, 256);
  4.   // Append header for new log
  5.   file.WriteLine("################################################################################" );
  6.   file.WriteLine("{0} is starting...", info.applicationName);
  7.   file.WriteLine("{0} version {1} {2}", info.applicationLongName, info.applicationVersion, info.applicationVersionFlag);
  8.   file.WriteLine("################################################################################" );
  9.   file.WriteLine("Legend :" );
  10.   file.WriteLine("PP : Application parameter (see INI file)" );
  11.   file.WriteLine("II : Informal message" );
  12.   file.WriteLine("EE : Blocking error" );
  13.   file.WriteLine("ee : Non-blocking error" );
  14.   file.WriteLine("WW : Warning message" );
  15.   file.WriteLine("################################################################################" );
  16.   file.WriteLine("" );
  17.  }
  18.  public void AddBlockingError(string message)
  19.  {
  20.   file.WriteLine("{0} : EE {1}", DateTime.Today.ToShortDateString(), message);
  21.   FatalErrors++;
  22.  }


 
Lorsque je lance le programme, ça plante avec ce message :

Code :
  1. C:\Documents and Settings\Administrateur\Mes documents\Visual Studio Projects\GN
  2. XCleanUp\bin\Debug>gnxcleanup
  3. Exception non gérée : System.IndexOutOfRangeException: Conflit d'accès d'E/S pro
  4. bable détecté lors de la copie dans la mémoire. Le package d'E/S n'est pas threa
  5. d-safe par défaut. Dans des applications multithread, l'accès au flux doit se fa
  6. ire de façon thread-safe, par exemple un wrapper thread-safe retourné par les mé
  7. thodes Synchronized de TextReader ou TextWriter. Cela s'applique également aux c
  8. lasses telles que StreamWriter et StreamReader.
  9.    at System.Buffer.InternalBlockCopy(Array src, Int32 srcOffset, Array dst, Int
  10. 32 dstOffset, Int32 count)
  11.    at System.IO.StreamWriter.Write(Char[] buffer, Int32 index, Int32 count)
  12.    at System.IO.TextWriter.WriteLine(String value)
  13.    at GNXCleanUp.logFile.Finalize()


 
Voici le fichier qu'il a commencé à écrire :

Code :
  1. ################################################################################
  2. GNXCleanUp is starting...
  3. GénériX automated clean up program version 0.0.1 alpha
  4. ################################################################################
  5. Legend :
  6. PP : Application parameter (see INI file)
  7. II : Informal message
  8. EE : Blocking error
  9. ee : Non-blocking error
  10. WW : Warning message
  11. ################################################################################
  12. 11/3/2005 : II Read INI file
  13. 11/3/20


 
Ca plante sur cet appel (log est une instance de la classe logFile) :

Code :
  1. log.AddBlockingError("GénériX path not set or wrong." );


Pourquoi ça plante ???


Message édité par Arjuna le 03-11-2005 à 16:39:16
Reply

Marsh Posté le 03-11-2005 à 16:31:56   

Reply

Marsh Posté le 03-11-2005 à 17:02:21    

Personne n'a une idée ? Parceque là, ça me lourde en fait :/

Reply

Marsh Posté le 04-11-2005 à 00:31:17    

c'est une race condition sur les I/O bufferisées. ça m'est déjà arrivé, et un gars de chez Microsoft m'avait répondu que ça venait du fait que les I/O bufferisées n'étaient pas thread safe, en étant toutefois très évasif
essaie ceci :

Code :
  1. public void AddBlockingError(string message)
  2. {
  3.    lock (this)
  4.    {
  5.       file.WriteLine("{0} : EE {1}", DateTime.Today.ToShortDateString(), message);
  6.       FatalErrors++;
  7.    }
  8. }


Message édité par Harkonnen le 04-11-2005 à 00:31:51

---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 04-11-2005 à 09:07:38    

OK, j'avais contourné le problème en ouvrant et fermant le fichier à chaque ligne. D'un côté c'est pourri, et d'un autre, pour un log c'est pas plus mal : si l'appli plante pour de bon, j'ai trace dans le log jusqu'au dernier élément logué, alors que sinon je perds tout le buffer avec.
 
Donc pour cette appli, je laisse comme ça. Par contre, je vais en avoir besoin pour générer un fichier de données dans une autre appli, je garde le topic en favori du coup. Merci !
 
Sinon, chose étonnante : mon appli n'est pas multithreadée pourtant. Sur un forum, j'avais en effet vu une explication similaire à la tienne, comme quoi c'est un bug du framework : StreamWriter et StreamReader sont indiqués comme thread-safe dans la doc, et pourtant ils ne le sont pas réellement. Seulement, ça ne devrait pas s'appliquer à mon cas, puisque mon appli est mono-thread :??:

Reply

Marsh Posté le 04-11-2005 à 15:17:49    

Je fais pareil avec mes logs : ouverture/fermeture à chaque fois, je fais ça depuis des années et ça marche bien.
 
Pour le bug : j'ai des trucs qui ressemblent de tps en tps (enfin je crois, j'ai le framework en anglais : c'est pas le même message :))
Je pense que c'est dû au fait que l'écriture sur fichier n'est pas synchrone, et que le StreamWriter est mal codé.
Un idée ça peut être d'utiliser Flush() sur le stream entre les écriture, pour forcer l'écriture physique...

Reply

Marsh Posté le 04-11-2005 à 15:43:26    

yep en effet.
 
mais mon problème, c'est que je vais bientôt devoir écrire un prog qui génère un fichier d'intégration de plusieurs centaines de milliers de lignes, et ce, assez souvent
 
et le but, c'est donc d'éviter d'ouvrir/fermer le fichier à chaque ligne, ni même de flusher, là je vais avoir un buffer de 1 Mo et je compte bien écrire sur le HD par lots de 1 Mo, d'autant plus que le disque est déjà extrêment stressé par l'activité di serveur

Reply

Marsh Posté le 04-11-2005 à 15:53:21    

Si tu veux éviter ce pb, fait ton propre système de bufferisation.
Un bête ArrayList :)

Reply

Marsh Posté le 04-11-2005 à 16:21:08    

ben ouais, je sens que je vais devoir bidouiller...
 
sinon, un truc...
 
.NET ne supporte pas les record ?
 
j'entends par là écrire une structure d'un coup dans un fichier (et savoir la relire)
 
par exemple, en VB je faisais ça (l'équivalent marche aussi en ADA, langage sur lequel j'ai appris cette technique) :
 

Code :
  1. struct commande
  2.     numero as string*8
  3.     client as string*12
  4.     date as string*10
  5.     EOL as string*2
  6. end struct
  7. struct ligne_commande
  8.     produit as string*16
  9.     quantite as string*3
  10.     prix as string*12
  11.     EOL as string*2
  12. end struct
  13. function creecommande()
  14.     dim cde as commande
  15.     dim lig as ligne_commande
  16.     dim fil as long
  17.     fil = freefile
  18.     open "truc.cde" as fil for write
  19.     cde.numero = "123"
  20.     cde.client = "toto"
  21.     cde.date = "04/11/2005"
  22.     cde.EOL = vbCrLf
  23.     put fil cde
  24.     lig.produit = "p1"
  25.     lig.quantite = "10"
  26.     lig.prix = "25,49"
  27.     lig.EOL = vbCrLf
  28.     put fil lig
  29.     close fil
  30. end function


 
ce qui donne dans le fichier :
 


123     toto        04/11/2005
p1              10 25,49        


 
Et ensuite, je peux relire ce fichier avec des "get fil cde" par exemple, ce qui va allimenter ma variable de type "commande" avec les données contenue dans le fichier.
 
J'ai cru comprendre que C# ne supportait même pas les chaines de taille fixe ! :??:
 
ps: ici, je ne gère que des string, mais on peut aussi stocker des types tels que INT, DATE, ou autres... y'a juste que passer par des chaines rend lisible le fichier pour analyse manuelle (parceque si j'ai une date en binaire dans mon fichier, je vais avoir un mal de chien à la relire ;))


Message édité par Arjuna le 04-11-2005 à 16:23:12
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed