[英]Why is the number objects in my WPF application increasing?
i write some code that reads a CSV file and convert it into a DateTable. 我写了一些读取CSV文件并将其转换为DateTable的代码。 In the next step it read the DataTable to get specific values.
在下一步中,它读取DataTable以获取特定值。 These values were saved in an object and this object will add to an ObserableCollection.
这些值保存在一个对象中,并且该对象将添加到ObserableCollection中。
XAML: 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- 
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>
Code-behind: 后台代码:
public MainWindow()
{
InitializeComponent();
MainViewModel mvm = new MainViewModel(filepath,pline);
listView.ItemSource = mvm.ProdOrderView;
}
MainViewModel: 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
}
}
When I load the CSV file every minute the amount of objects will increase extreamly. 当我每分钟加载CSV文件时,对象数量将急剧增加。 The Garbage Collector doesn't clear all old objects.
垃圾收集器不会清除所有旧对象。 can anybody help me to find this Problem?
有人可以帮助我找到这个问题吗?
my guess would be that your problem is that your using data tables where you don't need to. 我的猜测是您的问题是您不需要使用数据表。
A dataTable is a very complex item that is basically a code based database table and because of this is uses MarshalByValueComponent
, which tells you that this can't be automatically GC'ed and as such requires you to call Dispose once you have finished using it. dataTable是一个非常复杂的项目,基本上是基于代码的数据库表,因此使用了
MarshalByValueComponent
,它告诉您不能自动进行GC处理,因此需要在使用完之后调用Dispose。 。 (calling Dispose tells it to clean up its links to unmanaged code and be available to the garbage collector). (调用Dispose告诉它清除它到非托管代码的链接,并可供垃圾收集器使用)。
you have 2 options for triggering disposal a simple call to the Dispose function or a Using(){} statement 您有2个触发处置的选项,只需简单调用Dispose函数或Using(){}语句即可
you need to do this for all classes that are unmanaged (including StreamReader & FileStream) 您需要对所有非托管类(包括StreamReader和FileStream)执行此操作
as you aren't using the data table as a datatable, just a table then i would suggest removing it completely and just parsing your text file instead 因为您没有将数据表用作数据表,所以只建议使用一个表,则建议将其完全删除,然后解析您的文本文件
EDIT: 编辑:
Here as a quick and dirty model for a MVVM file parser 这是MVVM文件解析器的快速而肮脏的模型
XAML: 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>
Code behind: 后面的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
vm.ReadFile();
}
}
File Reader 文件阅读器
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);
}
}
}
}
Item Parser 项目解析器
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; }
}
Demo File used 演示文件已使用
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.