2016-06-27 23 views
-5

Ich habe ein Programm, das nicht genügend Arbeitsspeicher hat. Ich verstehe nicht warum, wie ich die object = null eingestellt habe, wenn es "behandelt" wurde.C# -Programm Nicht genügend Speicher

foreach (DataRow theRow in thisDataSet.Tables["Collection"].Rows) 
{ 
    LS_BatchAID = Convert.ToString(theRow["BatchAID"]); 
    LS_Batch = Convert.ToString(theRow["Batch"]); 
    LS_ID = Convert.ToString(theRow["ID"]); 
    CL_Batch Batch = new CL_Batch(LS_BatchAID, LS_ID, LS_Batch); 
    Batch = null; 
} 

thisConnection.Close(); 

ich diesen Fehler: System.OutOfMemoryException‘ist in mscorlib.dll aufgetreten Während das Programm läuft und Taskmanager zu beobachten, kann ich den Speicherverbrauch steigen linear in Übereinstimmung mit der Anzahl der Iterationen des Codes sehen.

Wie soll ich ein Programm erstellen, das Speicherverbrauch/Speicherauszug nicht erhöht?

CL_Batch: 

class CL_Batch 
    { 
     private string BatchAID; 
     private string ID; 
     private string Batch; 
     private string pathPDF; 
     private string pathCPR; 
     private string pathLog; 
     private string DateXMLGenerated; 

     private string[] IDType; 
     private string[,] IDTypes; 
     private string[] Files; 
     private DateTime Dates; 
     private byte[] pdfContent; 
     private string XMLContent; 
     private string[] RefNbr; 

     public CL_Batch(string IV_BatchAID, string IV_ID, string IV_Batch) 
     { 
      this.Dates = DateTime.Now; 

      this.DatoXMLGenerated = "" + Dato.Date.Year.ToString() + "-" + BuildNumber(true, 2, Dato.Date.Month.ToString()) + "-" + BuildNumber(true, 2, Dato.Date.Day.ToString()) + ""; 
      this.BatchAID = IV_BatchAID; 
      this.ID = IV_ID; 
      this.Batch = IV_Batch; 
      this.pathPDF = @"C:\path\TempFiles\path\" + this.ID + ".Pdf"; 
      this.pathCPR = @"C:\path\TempFiles\"; 
      this.pathLog = @"C:\path\Log\" + this.Batch + ".txt"; 

      setRefnbr(); 

       // Set array with mappings of ID between partners. 
       setLegitimationsTyper(); 

       // ensure log is available ([NameOfLog]). 
       prepareLog(); 

       // Find all files for archive. 
       getFileNames(); 

       // Move files C:\path\TempFiles\ 
       if (this.getFiles() == true) 
       { 
        // Create PDF's. 
        makePDF(); 

        // Insert PDF's in database. 
        insertPDF(); 

        // Create XML files. 
        makeXML(); 

        // Insertt XML in database. 
        insertXML(); 

       } 



     public string getBatchAID() 
     { 
      return this.BatchAID; 
     } 

     public string getID() 
     { 
      return this.ID; 
     } 

     public string getBatch() 
     { 
      return this.Batch; 
     } 

     public string getIDTyper(string IV_Code, bool kode) 
     { 

      for (int i = 0; i <= this.IDTypes.GetUpperBound(0); i++) 
      { 
       if (this.IDTypes[i, 0] == IV_Kode) 
       { 
        if (Code == true) 
        { 
         return this.LegitimationsTyper[i, 1]; 
        } 
        else 
        { 
         return this.LegitimationsTyper[i, 2]; 
        } 
       } 
      } 
      return ""; 
     } 
} 

/******************************************/

/** UPDATE # 1 **************************/

Fair enough! Missbrauch des Konstruktors. Ich verstehe den Punkt - Aber: Was ist das Problem wirklich?

Wenn ich das tue, wie ich schon im Vergleich zu diesem Beispiel getan hat:

CL_Batch Batch = new CL_Batch(LS_BatchAID, LS_ID, LS_Batch); 

Batch.setRefnbr(); 
Batch.setIDTypes(); 
Batch.prepareLog(); 
Batch.getFileNames(); 
Batch.makePDF(); 
Batch.insertPDF(); 
Batch.makeXML(); 
Batch.insertXML(); 
Batch = null; 

Was ist dann der wirkliche Unterschied ist? Wenn es auf verschiedene Arten wäre, ein paar Zahlen hinzuzufügen, dann würde es mit den gleichen Anweisungen enden.

First program: 
xor ax, ax 
mov ax, 10 
add ax, 10 

Second program: 
xor ax, ax 
mov ax, 10 
add ax, 10 

So wie ich es sehen, dass es am Ende keinen Unterschied (I recon, dass ich das Konzept der oop mißbrauchen, aber das Endprodukt ist das gleiche - ich erwarte)

mir bitte Rat, meine Täuschung in Bezug auf .

Vielen Dank im Voraus. /** UPDATE # 1/ /****************************************** **

+8

Was CL_Batch ist? – BugFinder

+2

Das Reduzieren Ihres Snippets zu einer 'foreach' ist keine Möglichkeit, den Lärm für uns zu minimieren - es wäre besser, wenn Sie nur das Rauschen in der gesamten Klasse reduzieren und uns diese reduzierte Klasse zeigen - Sie wissen nie, dass es etwas ist nicht in Ihrer Foreach-Schleife –

+1

Ich denke, Ihr Problem könnte um die Menge der Zeichenfolgen in Ihrem Speicher sein, aber Sie müssen dies profilieren, um die tatsächliche Antwort zu finden, verwenden dotMemory oder ähnliches –

Antwort

0

Auch wenn ich mit den Vorschlägen bezüglich schlechtem Konstruktorcode nicht einverstanden bin, muss ich anerkennen, dass es einen Unterschied gemacht hat und dass der Code nach Entfernen von Code aus dem Konstruktor wie vorgesehen funktioniert. Wenn jemand eine gute Erklärung für mich hat, würde ich es gerne hören. Gibt es trotzdem kann ich euch geben (BugFinder, Callum Linington, Mixxiphoid, ManoDestra, Mike Robinson, Matthew Whited, Scott Hannen) Kredit für die Lösung?

Dies ist der Code, das funktioniert:

foreach (DataRow theRow in thisDataSet.Tables["Collection"].Rows) 
{ 
    LS_BatchAID = Convert.ToString(theRow["BatchAID"]); 
    LS_Batch = Convert.ToString(theRow["Batch"]); 
    LS_ID = Convert.ToString(theRow["ID"]); 
    CL_Batch Batch = new CL_Batch(LS_BatchAID, LS_ID, LS_Batch); 
    Batch.setRefnbr(); 
    Batch.setIDTypes(); 
    Batch.prepareLog(); 
    Batch.getFileNames(); 
    Batch.makePDF(); 
    Batch.insertPDF(); 
    Batch.makeXML(); 
    Batch.insertXML(); 
} 
thisConnection.Close(); 
+1

Dies ist keine Antwort. Sie sollten dies entfernen. Außerdem machen Sie immer noch diese ganze Verarbeitung in Ihrer Datenschleife. Und Sie brauchen am Ende nicht die Zeile Batch = null. Es wird nur einmal in jeder Iteration instanziiert und es wird trotzdem wieder instantiiert, so dass es sinnlos ist, es auf null zu setzen. Das Problem liegt in den nachfolgenden Methoden. Ich würde nicht tun, was du hier machst. Ich würde diese Verarbeitung in einer separaten Schleife außerhalb dieser durchführen, aber zumindest jetzt können Sie ein wenig besser erkennen, wo der Speicherverlust auftritt, weil Sie die Logik ein wenig ausgebrochen haben. – ManoDestra

+0

@ManoDestra Danke für Ihre Antwort. In Bezug auf das Programm bewegt sich der Speicherverbrauch jetzt wie vorgesehen auf und ab. Über Ihre Aussage zur Verarbeitung innerhalb der Datenschleife. Wie soll ich es machen, wenn nicht so? Danke im Voraus. Bitte sei sanft mit mir. Ich werde hier verprügelt. –

+1

Zwei Möglichkeiten, dies zu tun. Die Art und Weise, wie Sie es hier gemacht haben, ist besser, da Sie ein besseres Gefühl für die Linie haben sollten, wo der Speicherverbrauch das Programm umfällt. Und von dort aus können Sie einen Drilldown durchführen, um herauszufinden, warum. Persönlich würde ich alle diese Methodenaufrufe (.setRefnbr(), setIDTypes() usw.) in eine zweite Schleife verschieben. Durchlaufen Sie also die Zeilen Ihrer Tabelle wie oben, fügen Sie jedoch jedes CL_Batch einer Liste hinzu. Durchlaufen Sie dann diese Liste nach dieser Schleife und führen Sie stattdessen die Methodenaufrufe durch. Sinn ergeben? – ManoDestra

3

Dies ist ein Stich im Dunkeln, da wir Ihren Code nicht sehen können. Sie erstellen PDFs. Dies beinhaltet oft entweder eine Art von COM-Objekt oder einen Speicher-Stream. Was auch immer Sie zum Erstellen dieser PDFs verwenden, wird nicht beseitigt oder bereinigt, sodass jedes von Ihnen erstellte PDF im Speicher verbleibt, bis Sie es nicht mehr benötigen. Ich würde mir die Dokumentation für die von Ihnen verwendete Komponente genauer ansehen. Wenn etwas implementiert IDisposable stellen Sie sicher, dass Sie es entsorgen.

Verwandte Themen