为什么我的WPF应用程序中的数字对象增加了?

时间:2016-12-12 14:44:08

标签: c# wpf memory

我写了一些代码来读取CSV文件并将其转换为DateTable。在下一步中,它会读取DataTable以获取特定值。这些值保存在对象中,此对象将添加到ObserableCollection。

XAML:

<ListView ItemsSource="{Binding ProdOrderView}" x:Name="listView"    Margin="9,70,112,34" AlternationCount="2" FontSize="14">
            <ListView.ItemContainerStyle>
                <Style TargetType="{x:Type ListViewItem}">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                    <Style.Triggers>
                        <Trigger Property="ItemsControl.AlternationIndex"  Value="0">
                            <Setter Property="Background" Value="White" />
                        </Trigger>
                        <Trigger Property="ItemsControl.AlternationIndex"  Value="1">
                            <Setter Property="Background" Value="LightGray" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.View >
                <GridView >
                    <GridViewColumn  Header="Fauf" Width="Auto">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock  Text="{Binding Fauf}" TextAlignment="Right" Name="fauf"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn  Header="Prod-Start" Width="Auto">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock  Text="{Binding Start}" TextAlignment="Center" Name="start"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Rück- &#xa;stand" Width="Auto">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock x:Name="inRueck"  Text="{Binding InRueck}" TextAlignment="Center" />
                                <DataTemplate.Triggers>
                                    <DataTrigger Binding="{Binding InRueck, Converter={StaticResource ColorConverterInRueck}}" Value="delay">
                                        <Setter TargetName="inRueck" Property="Background" Value="Red" />
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding InRueck, Converter={StaticResource ColorConverterInRueck}}" Value="inTime">
                                        <Setter TargetName="inRueck" Property="Background" Value="Green" />
                                    </DataTrigger>
                                </DataTemplate.Triggers>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="heute" Width="Auto"  >
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock x:Name="Heute" Text="{Binding Heute}" TextAlignment="Center" />
                                <DataTemplate.Triggers>
                                    <DataTrigger Binding="{Binding Heute}" Value="X">
                                        <Setter TargetName="Heute" Property="Background" Value="CornflowerBlue" />
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Heute}" Value="?">
                                        <Setter TargetName="Heute" Property="Foreground" Value="DarkViolet" />
                                    </DataTrigger>
                                </DataTemplate.Triggers>
                            </DataTemplate>

                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="morgen" Width="Auto" >
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock  Text="{Binding Morgen}" TextAlignment="Center" Name="Morgen"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="+2" Width="Auto" >
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock  Text="{Binding Uebermorgen}" TextAlignment="Center" Name="Uebermorgen"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                ...

                </GridView>
            </ListView.View>
        </ListView> 

代码隐藏:

 public MainWindow()
    {
        InitializeComponent();
        MainViewModel mvm = new MainViewModel(filepath,pline);
        listView.ItemSource = mvm.ProdOrderView;
    }

MainViewModel:

class MainViewModel
{
    #region Private Felder
    private ObservableCollection<ProductionOrder> _prodOrderList;

    private ListCollectionView _prodOrderView;
    #endregion

    #region Konstruktor
    public MainViewModel(string filepath, string pline)
    {
        // ProductionOrderliste initialisieren
        _prodOrderList = new ObservableCollection<ProductionOrder>();           

        _prodOrderList.Clear();
        fillObject(filepath, pline, ref _prodOrderList);

        // ListCollectionView initialisieren
        _prodOrderView = new ListCollectionView(_prodOrderList);

    }

    #endregion

    #region Öffentliche Eigenschaften
    public ListCollectionView ProdOrderView
    {
        get { return _prodOrderView; }
    }


    #endregion

    #region ConvertCSVtoDataTabble
    public DataTable ConvertCSVtoDataTable(string filename)
    {
        //DataTable anlegen
        DataTable dataTable = new DataTable();
        dataTable.Columns.Clear();
        dataTable.Rows.Clear();
        dataTable.Clear();

        try
        {
            //Filestream anlegen, dadurch kann Datei auch gelesen werden, wenn sie geöffnet ist
            FileStream logFileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

            using (StreamReader streamReader = new StreamReader(logFileStream))
            {
                //Array mit allen Überschriften
                string[] headers = streamReader.ReadLine().Split(';');
                //Schleife durchläuft das Array headers
                foreach (string header in headers)
                {
                    //Der DataTable wird eine Spalte mit dem aktuellen header (Überschrift) hinzugefügt.
                    dataTable.Columns.Add(header);
                }
                //Schleife, die so lange gültig ist bis das Ende des Streams erreicht wurde
                while (!streamReader.EndOfStream)
                {
                    //Array mit allen Zeilen füllen
                    string[] rows = streamReader.ReadLine().Split(';');


                    //Der DataTable wird die Zeile mit dem aktuellen Werten der Zeile hinzugefügt.
                    dataTable.Rows.Add(rows);
                }
                //StreamReader wird geschlossen
                streamReader.Close();
                //Filestream wird geschlossen
                logFileStream.Close();
            }
        }
        catch(IndexOutOfRangeException e)
        {
            Console.WriteLine("Fehlercode:" + e);
            ConvertCSVtoDataTable(filename);
        }
            //gefüllte DataTable wird zurückgegeben
            return dataTable;

        }

    #endregion

    #region fillObbject
    public void fillObject(string filepath, string plinie, ref ObservableCollection<ProductionOrder> liste)
    {
        //DataTable res = new DataTable();
        //res.Columns.Clear();
        //res.Rows.Clear();
        //res.Clear();


        string emptyField = "\" \"";
        DataTable res = ConvertCSVtoDataTable(filepath);
        try
        {
            foreach (DataRow row in res.Rows) // Loop over the rows.
            {


                if (row["AFKO_PLTXT"].ToString() == plinie)
                {

                    ////Objekt anlegen
                    ProductionOrder order = new ProductionOrder();

                    //#region Prüft ob Sammelhinweis vorhanden
                    string sammel = "";
                    Queue<string> queue = new Queue<string>();

                    if (res.Columns.Contains("ZZTAG_MO"))
                    {
                        //Montag
                        if (row["ZZTAG_MO"].ToString() == "X")
                        {
                            sammel = "MO";
                            queue.Enqueue(sammel);
                        }
                        //Dienstag
                        if (row["ZZTAG_DI"].ToString() == "X")
                        {
                            sammel = "DI";
                            queue.Enqueue(sammel);
                        }
                        //Mittwoch
                        if (row["ZZTAG_MI"].ToString() == "X")
                        {
                            sammel = "MI";
                            queue.Enqueue(sammel);
                        }
                        //Donnerstag
                        if (row["ZZTAG_DO"].ToString() == "X")
                        {
                            sammel = "DO";
                            queue.Enqueue(sammel);
                        }
                        //Freitag
                        if (row["ZZTAG_FR"].ToString() == "X")
                        {
                            sammel = "FR";
                            queue.Enqueue(sammel);
                        }
                        //Samstag
                        if (row["ZZTAG_SA"].ToString() == "X")
                        {
                            sammel = "SA";
                            queue.Enqueue(sammel);
                        }
                        //Sonntag
                        if (row["ZZTAG_SO"].ToString() == "X")
                        {
                            sammel = "SO";
                            queue.Enqueue(sammel);
                        }


                    }
                    // string sammelList wird zusammengesetzt
                    string sammelList = "";
                    if (queue.Count > 0)
                    {
                        sammelList = "/";
                        while (queue.Count > 0)
                        {
                            if (queue.Count > 1)
                                sammelList += queue.Dequeue() + "+";
                            else
                            {
                                sammelList += queue.Dequeue();
                            }
                        }
                    }
                    #endregion
                    //das Objekt wird mit den entsprechenden Werten gefüllt
                    order.Fauf = row["EXTRA_APO"].ToString();
                    order.Start = row["GSTRP_KO"].ToString();
                    order.Vorgang = row["LTXA1_AFVC"].ToString();
                    order.Kundenauftrag = row["KDAUF_FK"].ToString() + sammelList;
                    order.Material = row["MATNR_PO"].ToString();
                    order.Materialbezeichnung = row["MAKTX_MAKT"].ToString();
                    order.Menge = row["AFKO_GAMNG"].ToString();
                    order.WE_Menge = row["WEMNG_PO"].ToString();
                    order.Ende = row["GLTRP_KO"].ToString();
                    order.Notiz = row["NOTIZ_TEXT"].ToString();
                    order.Ladedatum = row["LDDAT_VBEP"].ToString();
                    order.Dauer = row["FAUFDAUER_REST_KO"].ToString();

                    //führende Nullen werden entfernt falls vorhanden
                    order.Kundenauftrag = order.Kundenauftrag.TrimStart('0');
                    order.Material = order.Material.TrimStart('0');

                    if (order.Menge.Contains(","))
                    {
                        order.Menge = order.Menge.Remove(order.Menge.IndexOf(@","));
                    }
                    if (order.WE_Menge.Contains(","))
                    {
                        order.WE_Menge = order.WE_Menge.Remove(order.WE_Menge.IndexOf(@","));
                    }
                    order.Heute = "";
                    order.Morgen = "";
                    order.Uebermorgen = "";
                    order.Plus3 = "";
                    order.Plus4 = "";
                    order.Plus5 = "";

                    string inKlaerung = "";

                    //konvertiert String zu Datetime
                    DateTime newStartDate = convertDateTime(order.Start);
                    order.Start = newStartDate.ToString("dd.MM.yyyy");


                    //Berechne Verzug in Tagen
                    int verzugTage = (DateTime.Today - newStartDate).Days;
                    order.InRueck = verzugTage.ToString();

                    //konvertiert String zu Datetime
                    var newLadedatum = convertDateTime(order.Ladedatum);
                    order.Ladedatum = newLadedatum.ToString("dd.MM.yyyy");
                    if (inKlaerung != emptyField)
                    {
                        //X in der Spalte setzen, an dem Tag wo es gefertigt wird
                        if (verzugTage >= 0)
                        {
                            order.Heute = "X";
                        }
                        else
                        {
                            switch (verzugTage)
                            {
                                case -1:
                                    order.Morgen = "X";
                                    break;
                                case -2:
                                    order.Uebermorgen = "X";
                                    break;
                                case -3:
                                    order.Plus3 = "X";
                                    break;
                                case -4:
                                    order.Plus4 = "X";
                                    break;
                                case -5:
                                    order.Plus5 = "X";
                                    break;
                                default:
                                    break;
                            }

                        }
                    }
                    else
                    {
                        order.Heute = "?";
                    }
                    try
                    {
                        //konvertiert String zu Datetime
                        var newEndDate = convertDateTime(order.Ende);
                        order.Ende = newEndDate.ToString("dd.MM.yyyy");
                    }
                    catch (FormatException e)
                    {
                        Console.WriteLine("Fehlercode:" + e);
                        order.Ende = "Fehler";
                    }

                    // Prüft ob Vorgang leer ist 
                    if (order.Vorgang == emptyField)
                    {
                        order.Vorgang = "";
                    }

                    //Prüft ob Notiz leer ist
                    if (order.Notiz == emptyField)
                    {
                        order.Notiz = "";
                    }

                    //Prüft ob Dauer leer ist
                    if (order.Dauer == emptyField)
                    {
                        order.Dauer = "";
                    }


                    liste.Add(order);                                             
                }
            }               
        }

        catch (ArgumentException e)
        {

            Console.WriteLine("Fehlercode:" + e);
        }

    }
   // #endregion

    #region convertDateTime
    public DateTime convertDateTime(string date)
    {
        //konvertiert String zu Datetime
        DateTime newDate = DateTime.ParseExact(date,
                     "yyyyMMdd",
                      System.Globalization.CultureInfo.InvariantCulture);
        return newDate;

    }
    #endregion
}
}

当我每分钟加载CSV文件时,对象的数量会急剧增加。垃圾收集器不会清除所有旧对象。任何人都可以帮我找到这个问题吗?

1 个答案:

答案 0 :(得分:0)

我的猜测是你的问题是你不需要使用数据表。

dataTable是一个非常复杂的项目,基本上是基于代码的数据库表,因此使用MarshalByValueComponent,它告诉您这不能自动GC编辑,因此要求您在完成使用后调用Dispose。 (调用Dispose告诉它清理其非托管代码的链接并可供垃圾收集器使用)。

你有两个选项可以触发处理对Dispose函数或Using(){}语句的简单调用

你需要为所有非托管的类(包括StreamReader和FileStream)执行此操作

因为你没有使用数据表作为数据表,只是一张表然后我会建议完全删除它而只是解析你的文本文件

编辑:

这里是MVVM文件解析器的快速而肮脏的模型

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:FileViewModel x:Name="vm" />
    </Window.DataContext>

    <DockPanel >
        <DockPanel DockPanel.Dock="Top">
            <Button DockPanel.Dock="Right" Click="Button_Click">Read</Button>
            <TextBox Text="{Binding File}" />
        </DockPanel>
        <ListView ItemsSource="{Binding ItemCollection}">
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding field1}" Header="Feild1"/>
                    <GridViewColumn DisplayMemberBinding="{Binding field2}" Header="Field2"/>
                    <GridViewColumn DisplayMemberBinding="{Binding field3}" Header="Field3"/>
                    <GridViewColumn DisplayMemberBinding="{Binding field4}" Header="Field4"/>
                </GridView>
            </ListView.View>

        </ListView>
    </DockPanel>
</Window>

代码背后:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        this.InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        vm.ReadFile();
    }
}

文件阅读器

public class FileViewModel : INotifyPropertyChanged
{
    private string _File;

    public string File
    {
        get { return _File; }
        set
        {
            _File = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("File"));
        }
    }

    public ObservableCollection<ItemModel> ItemCollection { get; } = new ObservableCollection<ItemModel>();

    public event PropertyChangedEventHandler PropertyChanged;

    public void ReadFile()
    {
        ItemCollection.Clear();

        using (StreamReader reader = new StreamReader(File))
        {
            var header =  reader.ReadLine();
            while(!reader.EndOfStream)
            {
                var data = reader.ReadLine();
                var item = ItemModel.Create(header, data, ',');
                ItemCollection.Add(item);
            }
        }
    }
}

项目解析器

public class ItemModel
{
    public static ItemModel Create(string colstr, string datastr, char delimiter)
    {
        var cols = colstr.Split(delimiter);
        var data = datastr.Split(delimiter);

        var item = new ItemModel();

        item.field1 = int.Parse(GetValue(cols, data, "field1"));
        item.field2 = DateTime.Parse(GetValue(cols, data, "field2"));
        item.field3 = GetValue(cols, data, "field3");
        item.field4 = double.Parse(GetValue(cols, data, "field4"));
        return item;
    }
    public static string GetValue(string[] cols, string[] data, string colName)
    {
        var colid = Array.IndexOf(cols, colName);
        if (colid == -1)
            return null;
        else
            return data[colid];
    }

    public int field1 { get; set; }
    public DateTime field2 { get; set; }
    public string field3 { get; set; }
    public double field4 { get; set; }

}

使用的演示文件

field2,field1,field4,field3
01-Jan-16,1,1.1,a
02-Jan-16,2,2.2,b
03-Jan-16,3,3.3,c
04-Jan-16,4,4.4,d