DataTable-Speicher nicht freigegeben werden

Ich habe einen Prozess, der das laden von Daten laden einer großen Menge von Daten in die DataTable dann einige Daten verarbeiten, aber jedes mal, wenn der job fertig ist die DataLoader.exe(32bit, 1,5 G memory limit) entbindet nicht der gesamte Speicher genutzt wird.

Versuchte ich 3 Möglichkeiten, um Speicher freizugeben:

  1. DataTable.Klar() dann rufen DataTable.Dispose() (Release etwa 800 MB Speicher aber noch erhöhen 200 MB Speicher jedes mal, wenn Daten laden job fertig, nach 3 oder 4 mal laden von Daten, die out-of-memory-Ausnahme ausgelöst, weil es mehr als 1,5 G Arbeitsspeicher insgesamt)
  2. Set DataTable zu null (Kein Speicher freigegeben, und wählen Sie laden, wenn mehr Daten, die out-of-memory-exception geworfen)
  3. Aufruf DataTable.Dispose() direkt (Kein Speicher freigegeben, und wählen Sie laden, wenn mehr Daten, die out-of-memory-exception geworfen)

Folgenden ist der code, ich habe versucht, für die Prüfung(In der realen Programm-es wird nicht rekursiv aufgerufen, es wird ausgelöst durch ein Verzeichnis zu beobachten Logik. Dieser code ist nur zum testen. Sorry für die Verwirrung.):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace DataTable_Memory_test
{
class Program
{
    static void Main(string[] args)
    {
        try
        {
            LoadData();                
            Console.ReadKey();

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            Console.ReadKey();
        }
    }

    private static void LoadData()
    {
        DataTable table = new DataTable();
        table.Columns.Add("Dosage", typeof(int));
        table.Columns.Add("Drug", typeof(string));
        table.Columns.Add("Patient", typeof(string));
        table.Columns.Add("Date", typeof(DateTime));

        //Fill the data table to make it take about 1 G memory.
        for (int i = 0; i < 1677700; i++)
        {
            table.Rows.Add(25, "Indocin", "David", DateTime.Now);
            table.Rows.Add(50, "Enebrel", "Sam", DateTime.Now);
            table.Rows.Add(10, "Hydralazine", "Christoff", DateTime.Now);
            table.Rows.Add(21, "Combivent", "Janet", DateTime.Now);
            table.Rows.Add(100, "Dilantin", "Melanie", DateTime.Now);
        }
        Console.WriteLine("Data table load finish: please check memory.");
        Console.WriteLine("Press 0 to clear and dispose datatable, press 1 to set datatable to null, press 2 to dispose datatable directly");
        string key = Console.ReadLine();
        if (key == "0")
        {
            table.Clear();
            table.Dispose();
            Console.WriteLine("Datatable disposed, data table row count is {0}", table.Rows.Count);
            GC.Collect();   
            long lMemoryMB = GC.GetTotalMemory(true/* true = Collect garbage before measuring */) / 1024 / 1024; //memory in megabytes
            Console.WriteLine(lMemoryMB);

        }
        else if (key == "1")
        {
            table = null;
            GC.Collect();
            long lMemoryMB = GC.GetTotalMemory(true/* true = Collect garbage before measuring */) / 1024 / 1024; //memory in megabytes
            Console.WriteLine(lMemoryMB);
        }
        else if (key == "2")
        {
            table.Dispose();
            GC.Collect();
            long lMemoryMB = GC.GetTotalMemory(true/* true = Collect garbage before measuring */) / 1024 / 1024; //memory in megabytes
            Console.WriteLine(lMemoryMB);
        }
        Console.WriteLine("Job finish, please check memory");
        Console.WriteLine("Press 0 to exit, press 1 to load more data and check if throw out of memory exception");
         key = Console.ReadLine();
        if (key == "0")
        {
            Environment.Exit(0);
        }
        else if (key == "1")
        {
            LoadData();
        }
    }
  }
}
  • DataTable selbst nicht umsetzen Dispose() es wird die Methode aus der übergeordneten MarshalByValueComponent - und das nur zwei Dinge MarshalByValueComponent ruft Site.Container.Remove(this) wenn Sie die Daten der Tabelle in einem ISite (die du nicht in deinem code-Beispiel) und heben Sie den Disposed Ereignis. Es entbindet nicht von Ressourcen.
  • Ich weiß nicht, aber ich Wette, Sie bekommen Ihre Objekte freigegeben, aber Sie Probleme mit der Fragmentierung des Speichers. EDIT: OH, führen Sie das Programm ohne debugger im release-Modus ist, sehen Sie sich anders Verhalten. GC verhält sich ganz anders, wenn man einen debugger attached.
  • Danke. Aber in meinem Fall ist das laden von Daten innerhalb eines Verzeichnisses anschauen-exe. Um dies zu verhindern OutOfMemoery Ausnahme, was soll ich tun?
  • Ok, ich werde versuchen Sie in den release-Modus.
  • Läuft ohne debugger ist wichtiger, läuft im release-Modus macht kleinere änderungen, aber läuft ohne debugger macht großen Veränderungen, um das Verhalten.
  • Ich habe versucht zu laufen ohne debugger (ausführen der exe direkt), noch OutOfMemory-exception geworfen.
  • Lassen Sie uns weiter, diese Diskussion im chat.
  • Nur nicht die Wiederverwendung der gleichen Tabelle. Erstellen Sie ein neues jedes mal. Sie gewinnen absolut nichts, durch die Wiederverwendung der gleichen DataTable jedes mal, aber Sie müssen verhindern, dass die GC von der Reinigung unerwünschte Daten, wie change-tracking-Daten.
  • Mir scheint nicht, dass er erneut dieselbe DataTable
  • Hoppla, es ist viel schlimmer - den rekursiven Aufruf LoadData bedeutet, dass ältere DataTables sind gehalten, für immer!

InformationsquelleAutor mhan0125 | 2015-06-04
Schreibe einen Kommentar