IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Traitement Excel dans C#, plantage mémoire


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2009
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2009
    Messages : 194
    Par défaut Traitement Excel dans C#, plantage mémoire
    Bonjour à tous.

    Je travaille sur une application C#que je n'ai aps developpé moi-même.
    Cette appli fait tout un tas de chose, et particulierement des traitements sur fichiers Excel. Mais de très gros fichiers Excel, facilement quelques dizaine de milliers de lignes sur plusieurs dizaines de colonnes. Avec en plus, plusieurs sheet, avec ces fameuse lignes et colonnes.

    On a finit par me remonter des problèmes de plantage apparement dû à la taille des ces fichiers. En voulant reproduire les bugs, j'ai eu plusieurs type d'erreur :

    - Out of memory

    Au bout d'un moment de traitement, un pop up apparait et me balance un outofMemory Exception. C'est l'erreur la plus difficile à reproduire, car d'une part aléatoire, d'autre part ce sont souvent les autres bugs qui apparaissent avant.
    Cette exception apparait toujours l'un d'un traitement de gros fichiers Excel, parfois 500k lignes.

    - COM class factory et plein de thread Excel

    L'erreur la plus courante.
    Pendant le traitement, je vois beaucoup de task Excel qui se créées dans mon task manager.
    Nom : excel_task.png
Affichages : 478
Taille : 29,9 Ko
    Et il peu même parfois y en avoir plus.

    Du coup à un moment donné j'ai un "Excel a cessé de fonctionner", puis l'appli stop son traitement avec
    Nom : excel_popup.png
Affichages : 395
Taille : 19,2 Ko



    Ayant un peu regardé sur le net les problèmes de mémoire, je n'ai trouvé que des soucis en 32 bit, je suis en 64, je ne pense pas que ça vienne de là.
    Mais je ne trouve nul part traces de souci de cet ordre avec du C# ou du traitement Excel. Du coup je ne sais pas bien quoi faire...

    Je sais que dans le code, chaque ligne peut devenir un objet, et que ces objets peuvent être clonés, voire plusieurs fois. Mais j'ai du mal à penser que C# ne puisse gérer ça.
    De plus, le plantage se fait après la mise en mémoire des Excel dans l'appli, j'ai du mal à faire le lien entre les thred Excel, alors que tout est supposé être chargé dans des tableaux/objets.

    Merci de votre aide.

  2. #2
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 218
    Par défaut
    Si on lance 50 Excels que se soit en vbs, bat ou c# on risque d'avoir des soucis de mémoire évident.

    Le nombre de ligne colonne n'est pas très impressionnant. Ça ne devrait pas poser de problème après je ne sais pas quel traitement sont effectué dans Excel.

    Le programme as il réellement besoin de lancer autant d'instance d'Excel ? Pour moi c'est soit :
    - un bug
    - un gros soucis d'optimisation (oublie de fermer l'Excel qui vient d'être utilisé ...)

  3. #3
    Inactif  

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2012
    Messages
    4 903
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2012
    Messages : 4 903
    Billets dans le blog
    36
    Par défaut
    Bonjour,

    Excel a un très gros problème. Il doit avoir constamment tout le classeur en mémoire vive pour fonctionner. Excel 64 est moderne et peut utiliser la mémoire disponible sur un ordinateur 64 bits. Excel à 32 bits est une antiquité incapable d'adresser la totalité de la mémoire d'un système à 64 bits.

    Ceci dit, tu ne nous dis pas le plus important. Comment accèdes-tu à ton classeur Excel ? Si je me fie à tes images, tu le fais avec les bibliothèques Interop (PIAs).

    Il existe des façons d'accéder directement au fichier, de créer et modifier un fichier Office (2007 et suivants) sans même avoir Excel sur la machine. Mais là, je suis trop fainéant pour réécrire ce que je viens presque juste d'écrire.

    http://www.developpez.net/forums/d15...l/#post8578427

  4. #4
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    Salut

    evidemment, réécrire ton application est peut-être un brin compliqué mais j'aurais tendance à utiliser une librairie type EEplus pour jouer avec mes fichiers
    EXcel...

    Après, la multitude d'Excel ouvert, ça ressemble à des Task lancées en parallèle et qui chacune ouvre le bazar... donc, forcément, si chaque Task ouvre
    un excel pour travailler sur une partie du document, c'est pas du tout optimisé...

    Sachant que la "logique" voudrait qu'on ouvre une fois le document et qu'on utilise éventuellement des taches (task) pour travailler sur des parties différentes,
    non liées dans le traitement

  5. #5
    Membre très actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2009
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2009
    Messages : 194
    Par défaut
    Merci à tous d'avoir pris le temps de réflechir à mon problème.

    Alors je suis sur un sytème 64bit et effectivement, les bibliothèques utilisées sont les Interop (Icrosoft.Office.Interop...).
    J'ai eu également un peu de temps pour regarder ce qui avait été fait, et je n'aurai malheuresement aps le temps de refaire tout ce qui a été fait, avec une autres API.

    Après investigation, il semble effectivement que l'appli ouvre plusieurs Excel pour traiter différentes parties du document, et ne referme pas ces parties.
    Je suis tombé sur ce site : https://www.add-in-express.com/creat...l-com-objects/
    Qui explique qu'il faut fermer les objets COM. J'ai bien essayé, mais ça ne fonctionne pas du tout...

    Voilà ce que eux préconise:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    Excel.Application app = null;
    Excel.Workbooks books = null;
    Excel.Workbook book = null;
    Excel.Sheets sheets = null;
    Excel.Worksheet sheet = null;
    Excel.Range range = null;
     
    try
    {
        app = new Excel.Application();
        books = app.Workbooks;
        book = books.Add();
        sheets = book.Sheets;
        sheet = sheets.Add();
        range = sheet.Range["A1"];
        range.Value = "Lorem Ipsum";
        book.SaveAs(@"C:\Temp\ExcelBook" + DateTime.Now.Millisecond + ".xlsx");
        book.Close();
        app.Quit();
    }
    finally
    {
        if (range != null) Marshal.ReleaseComObject(range);
        if (sheet != null) Marshal.ReleaseComObject(sheet);
        if (sheets != null) Marshal.ReleaseComObject(sheets);
        if (book != null) Marshal.ReleaseComObject(book);
        if (books != null) Marshal.ReleaseComObject(books);
        if (app != null) Marshal.ReleaseComObject(app);
    }
    Voila ce que j'avais moi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     public static object[,] ReadFile(string filepath, string sheetname)
            {
                Application xlApp = null;
                Workbook wb = null;
                object[,] values = null;
                try
                {
                    xlApp = new ApplicationClass();
                    wb = xlApp.Workbooks.Open(filepath, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing);
                    Worksheet sh = (Worksheet)wb.Worksheets.get_Item(sheetname);
     
                    values = sh.UsedRange.Value2 as object[,];
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Sheet \"{0}\" does not exist in the Excel file", sheetname));
                }
                finally
                {
                    if (wb != null)
                       wb.Close(false, missing, missing);
     
                    if (xlApp != null)
                        xlApp.Quit();              
                }
     
                return values;
            }
    Et voila ce que j'ai éssayé de rajouter :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     public static object[,] ReadFile(string filepath, string sheetname)
            {
                Application xlApp = null;
                Workbook wb = null;
                object[,] values = null;
                try
                {
                    xlApp = new ApplicationClass();
                    wb = xlApp.Workbooks.Open(filepath, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing);
                    Worksheet sh = (Worksheet)wb.Worksheets.get_Item(sheetname);
    
                    values = sh.UsedRange.Value2 as object[,];
                    if (sh != null) Marshal.ReleaseComObject(sh);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Sheet \"{0}\" does not exist in the Excel file", sheetname));
                }
                finally
                {
                    /*                if (wb != null)
                                        wb.Close(false, missing, missing);
                     */
                    if (xlApp != null)
                        xlApp.Quit();
    
                  if (wb != null) Marshal.ReleaseComObject(wb);
                    
                }
    
                return values;
            }
    Malheuresement ça ne fonctionne pas, ça ne ferme rien du tout.
    Mais ça fait sens avec ce que vous disiez tous.

  6. #6
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 218
    Par défaut
    J'ai vérifier effectivement le process excel ne se ferme pas.
    Sauf avec ça même si c'est déconseiller de forcer la collecte du ramasse miette.
    http://www.craigmurphy.com/blog/?p=82

    J'avait eu le même soucis avec l'objet COM IE.

    Je rejoint donc l'avis de theMonz31.
    Il vaut mieux une seul instance d'Excel, qui fasse les opérations plutôt que de la fermer/rouvrir.
    Je ne pense pas que ton logiciel fasse du parallélisme.

Discussions similaires

  1. [XL-2013] Ajouter un traitement VBA dans un tableau Excel
    Par arnaudperfect dans le forum Excel
    Réponses: 4
    Dernier message: 23/10/2014, 16h06
  2. [AC-2003] Importation d'un fichier excel dans Access avec traitement
    Par Mishe dans le forum VBA Access
    Réponses: 2
    Dernier message: 12/03/2013, 16h23
  3. Réponses: 11
    Dernier message: 04/08/2010, 13h00
  4. Réponses: 2
    Dernier message: 03/06/2005, 10h19
  5. [VB6]PB d'importation d'un feuille Excel dans une MSFlexGrid
    Par mystere l dans le forum VB 6 et antérieur
    Réponses: 18
    Dernier message: 20/04/2004, 15h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo