Application C# qui plante (lecture ecriture fichier)

xamox
Messages postés
7
Date d'inscription
dimanche 21 décembre 2008
Statut
Membre
Dernière intervention
25 février 2010
- 31 déc. 2009 à 15:38
xamox
Messages postés
7
Date d'inscription
dimanche 21 décembre 2008
Statut
Membre
Dernière intervention
25 février 2010
- 9 janv. 2010 à 21:50
Bonjour a tous!!

Voila j'ai un problème avec mon application C# qui ne fait que planter.
En fait cette application ouvre un certains nombre de fichier binaire (sa peut aller jusqu'à 20 voir 25) elle lit le premier octet de chacun des fichiers, elle les comparent et écrit dans un autre fichier binaire (reconstruction) la valeur la plus récurrente. Elle fait de même avec l'octet suivant (lecture dans tous les fichier de l'octet n°2, comparaison pour trouver la valeur la plus récurrente et écriture a la suite du fichier reconstruction... et ce jusqu'à la fin du fichier.

Cependant mon application plante lorsque l'on clic sur un autre onglet pour faire autre chose (Donc quand elle passe en arrière plan). Sinon si on la laisse au premier plan elle arrive a se terminée généralement.

Les ressources utilisé sont quand même non négligeables: avec 4 fichiers j'ai déja 170 MO d'utilisée pour le processus.

Que faut il que je fasse pour remédier a ce problème (comment diminuer les ressources ou alors séparer en plusieurs processus???)).

Ci dessous mon code bon il se peut qu'il comporte des erreurs pour trouver la valeur la plus récurrente mais le problème je pense ne vienne pas de là.

Et pardon pour la programmation un peu "boucher".

public partial class Interface : Form
    {

        const int NB_MAX_FICHIER = 25;

        System.Windows.Forms.OpenFileDialog MonBrowser = new System.Windows.Forms.OpenFileDialog();
        System.IO.BinaryWriter RecoveryNAND = new System.IO.BinaryWriter(File.Create("RecoveryNAND.bin"));
        System.IO.BinaryReader[] TabFichierBIN = new System.IO.BinaryReader[NB_MAX_FICHIER];
        Byte[] Tabbyte = new Byte[NB_MAX_FICHIER];
        int[] TabRecurrence = new int[NB_MAX_FICHIER];
        Byte Val;
        int i = 0;
        int iNbeDifferent = 0;    


        public Interface()
        {
            InitializeComponent();
        }

        public void LectureBin()
        {
            Tabbyte[0] = TabFichierBIN[0].ReadByte();
            TabRecurrence[0] = 1;
            iNbeDifferent = 1;

            for (long j = 1; j < i; j++)
            {
                Val = TabFichierBIN[j].ReadByte();
                Check_Exist(Val);
                //MessageBox.Show("different=" + iNbeDifferent);
            }
            Traitement();
        }

        public void Check_Exist(Byte Valeur)
        {
            int j = 0;
            bool bFind = false;

            while((j < iNbeDifferent) && (bFind==false))
            {
                if (Valeur == Tabbyte[j])
                {
                    TabRecurrence[j]++;
                    bFind = true;
                }
                else if (j == (iNbeDifferent - 1))
                {
                    Tabbyte[iNbeDifferent] = Valeur;
                    TabRecurrence[iNbeDifferent]=1;
                    iNbeDifferent++;
                }
                j++;   
            }
        }

        public void Traitement()
        {
            int iMax = 0;
            int index=0;
            int iMax2 = 0;
            int j = 0;

            while (j < iNbeDifferent)
            {
                if ((TabRecurrence[j] > iMax) && (TabRecurrence[j]>(i/2)))
                {
                    iMax = TabRecurrence[j];
                    index=j;
                }
                else if (TabRecurrence[j] == iMax)
                {
                    iMax2 = TabRecurrence[j];
                }
                j++;
            }

            if (iMax > iMax2)
            {
                RecoveryNAND.Write(Tabbyte[index]);
            }
            else
            {
                //listBox2.Items.Add("Conflit de récurrence:" + iMax + "/" + iMax2);
            }
        }

        public void RAZ()
        {
            iNbeDifferent = 1;
            i = 0;

        }


        private void buttonAjoutDump_Click(object sender, EventArgs e)
        {
            MonBrowser.Multiselect = true;
            MonBrowser.ShowDialog();
            for (int j = 0; j < MonBrowser.FileNames.Length; j++)
            {
                TabFichierBIN[i] = new System.IO.BinaryReader(File.Open(MonBrowser.FileNames[j], FileMode.Open));
                listBox1.Items.Add(MonBrowser.FileNames[j]);
                i++;
            }
        }

        private void buttonComparer_Click(object sender, EventArgs e)
        {
            
        }

        private void aideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Aide monAide = new Aide();
            monAide.ShowDialog();
        }

        private void aProposToolStripMenuItem_Click(object sender, EventArgs e)
        {
            APropos monAPropos = new APropos();
            monAPropos.ShowDialog();
        }

        private void buttonCreeNAND_Click(object sender, EventArgs e)
        {
            long LongeurFichier;
            LongeurFichier = TabFichierBIN[0].BaseStream.Length;

            while (progressBar1.Value < LongeurFichier)
            {
                    LectureBin();
                    progressBar1.PerformStep();
            }

                 MessageBox.Show("Fin");
                
        }
    }
} 


Merci pour votre aide.

7 réponses

leprov
Messages postés
1160
Date d'inscription
vendredi 23 juillet 2004
Statut
Membre
Dernière intervention
21 octobre 2010
17
4 janv. 2010 à 09:32
"Ca plante" c'est un peu léger pour qu'on t'aide. le message de l'exception serait le bienvenu.
cependant, je suppose qu'il s'agit d'un probleme de lecture ecriture dans un fichier. Tu ouvre des fichiers, mais tu ne gardes pas de références sur les fichiers en question. PAsser a un autre tab doit déclencher une garbage collection, et fermer les handle de tes fichiers, donc tes lectures écritures plantent. Ouvre et ferme tes fichiers proprement en gardant des références sur les fichiers ouverts
0
krimog
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Membre
Dernière intervention
14 février 2015
51
4 janv. 2010 à 14:49
Salut

Je n'ai pas pris le temps de regarder ton code, mais 170 Mo, ça me parait ENORME pour un programme comme ça. Théoriquement, tu n'es pas censé avec les fichiers en mémoire. Juste les StreamReaders et le StreamWriter (qui ne sont pas des copies mémoire du fichier mais juste une sorte de tête de lecture / d'écriture).

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
0
xamox
Messages postés
7
Date d'inscription
dimanche 21 décembre 2008
Statut
Membre
Dernière intervention
25 février 2010

4 janv. 2010 à 19:53
Excuser moi en fait quand je dit que sa plante ben c'est pas un message d'erreur qui apparait mais bien l'interface qui ne répond plus. Cependant si je lance le programme et que je ne fait rien d autre (laisse finir l application) tout marche bien.
J'ai remarquer que en fait a partir du moment ou j ai par exemple deplacer la fenêtre de mon application et bien celle si ne répond plus (sablier souris et message sur la fenetre "(ne repond pas)") jusqu'à la fin de l'exécution de ma boucle
while (progressBar1.Value < LongeurFichier)
            {
                    LectureBin();
                    progressBar1.PerformStep();
            }


La lecture de tout les fichiers octet par octet prend beaucoup de temps et j'ai lut sur msdn.microsoft qu'il peut se produire se genre de problême dans le cas d'un calcul long ou d'une action qui dure longtemps et qui bloquerais en quelques sorte la réactivité de l'interface.
La solution proposé serais d'utilisé un Thread différent pour faire l'opération qui prend du temps.
Je me renseigne sur les Threads (je sais pas trop se que c'est) et notamment sur la classe BackgroundWorker
Voila qu'en penser vous???

PS:
J'ai depuis modifier mon code(l'ancien était trop crade ).
0
xamox
Messages postés
7
Date d'inscription
dimanche 21 décembre 2008
Statut
Membre
Dernière intervention
25 février 2010

4 janv. 2010 à 22:10
Bon alors voici le programme avec relifting complet et tentative d'ajout d'un autre thread pour faire la comparaison et l'écriture de mon fichier:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;


namespace RecoNAND
{
    public partial class Interface : Form
    {

        const int NB_MAX_FICHIER = 25;

        System.Windows.Forms.OpenFileDialog MonBrowser = new System.Windows.Forms.OpenFileDialog();//Pour aller chercher les fichiers
        System.IO.BinaryWriter RecoveryNAND = new System.IO.BinaryWriter(File.Create("RecoveryNAND.bin"));//NAND reconstruite
        List<System.IO.BinaryReader> ListFichierBIN = new List<System.IO.BinaryReader>();//Pour stocker les fichiers

        long LongeurFichier = -1;



        public Interface()
        {
            InitializeComponent();
        }

        public void RAZ()
        {
            listBox1.Items.Clear();
            listBox2.Items.Clear();
            ListFichierBIN.Clear();
            LongeurFichier = -1;
        }


        private void buttonAjoutDump_Click(object sender, EventArgs e)
        {
            MonBrowser.Multiselect = true;
            MonBrowser.ShowDialog();
            listBox1.Items.Remove("Selectionner les fichiers...");

            foreach(string PathFile in MonBrowser.FileNames)
            {  
                ListFichierBIN.Add(new System.IO.BinaryReader(File.Open(PathFile, FileMode.Open)));
                listBox1.Items.Add(PathFile);
            }
        }

        private void buttonComparer_Click(object sender, EventArgs e)
        {
            // Enable the Cancel button while 
            // the asynchronous operation runs.
            this.cancelAsyncButton.Enabled = true;
            backgroundWorker1.RunWorkerAsync("Comparer");
        }

        private void Comparer_Fichier(BackgroundWorker worker, DoWorkEventArgs e)
        {
            if (worker.CancellationPending)
            {
                e.Cancel = true;
            }
            else
            {
                //Mettre ici la comparaison des fichiers
            }
        }

        private void aideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Aide monAide = new Aide();
            monAide.ShowDialog();
        }

        private void aProposToolStripMenuItem_Click(object sender, EventArgs e)
        {
            APropos monAPropos = new APropos();
            monAPropos.ShowDialog();
        }

        private void buttonCreeNAND_Click(object sender, EventArgs e)
        {
            LongeurFichier = -1;

            foreach (System.IO.BinaryReader FileBIN in ListFichierBIN)
            {
                if (LongeurFichier == -1)
                {
                    LongeurFichier = FileBIN.BaseStream.Length;
                }
                else if (FileBIN.BaseStream.Length != LongeurFichier)
                {
                    MessageBox.Show("Les fichiers doivent avoir la même taille.");
                    CloseAllFiles(ListFichierBIN);
                    listBox1.Items.Clear();
                    listBox1.Items.Add("Selectionner les fichiers...");
                    listBox2.Items.Add("Impossible de générer la NAND car les fichiers sont de tailles différentes.");
                    break;
                }
            }

            // Enable the Cancel button while 
            // the asynchronous operation runs.
            this.cancelAsyncButton.Enabled = true;
            backgroundWorker1.RunWorkerAsync("Creation_NAND");
        }

        public void CloseAllFiles(List<System.IO.BinaryReader> ListToClose)
        {
            foreach (System.IO.BinaryReader File in ListToClose)
            {
                File.Close();
            }
        }

        public void Creation_fichier_NAND(BackgroundWorker worker, DoWorkEventArgs e)
        {
            int percentComplete = 0;
            long nbeLu = 0;

            for (nbeLu = 0; nbeLu < LongeurFichier; ++nbeLu)
            {            
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                }
                else
                {
                        //Ajouter ici la lecture et l'ecriture de la nouvelle NAND dans le fichier RecoveryNAND
                        percentComplete = (int)((float)nbeLu / (float)LongeurFichier * 100);
                        worker.ReportProgress(percentComplete);
                }
            }
        }

        private void cancelAsyncButton_Click(System.Object sender,
            System.EventArgs e)
        {
            // Cancel the asynchronous operation.
            this.backgroundWorker1.CancelAsync();

            // Disable the Cancel button.
            cancelAsyncButton.Enabled = false;
        }

        // This event handler is where the actual,
        // potentially time-consuming work is done.
        private void backgroundWorker1_DoWork(object sender,
            DoWorkEventArgs e)
        {
            // Get the BackgroundWorker that raised this event.
            BackgroundWorker worker = sender as BackgroundWorker;

            // Assign the result of the computation
            // to the Result property of the DoWorkEventArgs
            // object. This is will be available to the 
            // RunWorkerCompleted eventhandler.

            if ((string)e.Argument == "Creation_NAND")
            {
                Creation_fichier_NAND(worker,e);
            }

            else if ((string)e.Argument == "Comparer")
            {
                Comparer_Fichier(worker, e);
            }
        }

        // This event handler deals with the results of the
        // background operation.
        private void backgroundWorker1_RunWorkerCompleted(
            object sender, RunWorkerCompletedEventArgs e)
        {
            // First, handle the case where an exception was thrown.
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {
                // Next, handle the case where the user canceled 
                // the operation.
                // Note that due to a race condition in 
                // the DoWork event handler, the Cancelled
                // flag may not have been set, even though
                // CancelAsync was called.
                listBox2.Items.Add("Opération annulée");
            }
            else
            {
                // Finally, handle the case where the operation 
                // succeeded.
                listBox2.Items.Add("Opération terminée avec succès");
            }

            // Enable the UpDown control.
            this.buttonCreeNAND.Enabled = true;

            // Enable the Start button.
            this.buttonComparer.Enabled = true;

            // Disable the Cancel button.
            this.cancelAsyncButton.Enabled = false;
        }

        // This event handler updates the progress bar.
        private void backgroundWorker1_ProgressChanged(object sender,
            ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
        }
    }
}


Dans ce code il n'y a pas encore la lecture et l'écriture dans un fichier (je veut que sa marche avant de continuer) mais j'ai fait une boucle qui tourne autant de fois que je devrais lire dans mes fichiers:

for (nbeLu = 0; nbeLu < LongeurFichier; ++nbeLu)
            {            
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                }
                else
                {
                        //Ajouter ici la lecture et l'ecriture de la nouvelle NAND dans le fichier RecoveryNAND
                        percentComplete = (int)((float)nbeLu / (float)LongeurFichier * 100);
                        worker.ReportProgress(percentComplete);
                }
            }


Sauf que comme d'habitude sa plante::
Quand je lance l'application au début elle me prend environ 15MO. J'ouvre les fichiers l'application prend toujours 15MO mais quand je click sur mon bouton pour lancer la méthode buttonCreeNAND_Click et bien l'application prend de plus en plus de volume en mémoire jusqu'à 1,5Go!!! Et après ben forcément sa me lève une erreur du style "Out of memory".

D'où vient mon problème???
Mon BackgroundWorker et il bien configurer??? J'ai en gros copier ici: http://msdn.microsoft.com/fr-fr/library/waw3xexc%28VS.80%29.aspx pour exécuter le composant BackgroundWorker.

Je n'ai plus d'idée pour débugger.
Merci de votre aide
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
nhervagault
Messages postés
6063
Date d'inscription
dimanche 13 avril 2003
Statut
Modérateur
Dernière intervention
15 juillet 2011
35
6 janv. 2010 à 22:18
Salut,

Peux-tu mettre dans un fichier (exemple sur ci-joint.fr) un exemple de code qui produit le probleme.

Il y a peut etre un probleme l'ouverture des fichiers et la lecture n'est peut etre pas sur le meme thread.

Bon dev
0
xamox
Messages postés
7
Date d'inscription
dimanche 21 décembre 2008
Statut
Membre
Dernière intervention
25 février 2010

6 janv. 2010 à 22:27
Ben le code est juste au dessus de ton message en fait j ai même virer toute les lecture et écriture de fichier mais rien a faire l application prend du volume en taille mémoire.Jai du louper un truc avec mon composant backgroundWorker
0
xamox
Messages postés
7
Date d'inscription
dimanche 21 décembre 2008
Statut
Membre
Dernière intervention
25 février 2010

9 janv. 2010 à 21:50
Bon ben voila j'ai finit par y arriver tous seul.
La dernière version marchais presque c est juste qu'il ne faut pas effectuer un événement worker.ReportProgress(percentComplete) à chaque boucle. Sa fait toujours autant ramer en fait.
Donc faut déclencher worker.ReportProgress(percentComplete) moin de fois j'ai donc ajouter un modulo qui limite le nombre de mise a jour de la progressBarre:
if (nbeLu % modulo == 0)
                        {
                            percentComplete += 1;
                            worker.ReportProgress(percentComplete);
                        }


avec
long modulo = LongeurFichier / 19;

Voila c'est résolu.
0