Я пишу код, который читает CSV-файл и преобразует его в DateTable. На следующем шаге он читает DataTable для получения конкретных значений. Эти значения были сохранены в объекте, и этот объект добавит в ObserableCollection.Почему число объектов в моем приложении WPF увеличивается?
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-за:
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 файл каждую минуту количество объектов будет extreamly увеличиваться. Сборщик мусора не очищает все старые объекты. может ли кто-нибудь помочь мне найти эту проблему?
всегда будет некоторое увеличение, как вы загружаете больше данных в коде, но это должен быть линейный рост по отношению к данным – MikeT
Даже если это всегда тот же файл? – Nesslae
, если вы загружаете новые данные, тогда да, после того, как загрузка будет завершена, GC очистит объекты, которые больше не используются, которые, если вы используете ресурсы выпуска, должны снова вернуть вас обратно.также помните, что wpf использует, по возможности, ленивую загрузку, если вы загружаете 5000 предметов в сетку, тогда она будет загружать только те, которые на самом деле видны на экране, так как вы перемещаетесь по списку, будут загружены новые элементы, если они не будут очень сложный это лучший способ сделать это – MikeT