I have a following situation.
There is one line chart which can display 10 lines at a time. Each line contain 355 data points. User can turn each of the line on and off by selecting/deselecting data objects which contain the data series.
Chart lines look like this:
开发者_Go百科 <charting:LineSeries ItemsSource="{Binding DataSlot1, Mode=OneWay}"
IndependentValueBinding="{Binding X, Mode=OneWay}"
DependentValueBinding="{Binding Y, Mode=OneWay}"
DataPointStyle="{StaticResource styleForDataSlot1}"
IsSelectionEnabled="False" />
and I load the data into each of 10 "data slots" from ViewModel as follows.
Data points are structs:
public struct SimpleDataPoint
{
public double X { get; set; }
public double Y { get; set; }
}
ViewModel contains "data slots":
private SimpleDataPoint[][] _dataSlots;
and ViewModel exposes data slots through properties:
public SimpleDataPoint[] DataSlot1
{
get { return _dataSlots[0]; }
}
when I load data into the slot, I do something like this:
_dataSlots[freeSlot] = myDataProvider.GetPoints();
to clear data from the slot I do:
_dataSlots[slotToClear] = null;
After each add/remove data operation for a slot I call
OnPropertyChanged("DataSlot1");
The problem: if the user works for a long time adding and removing data lines for the chart, the memory usage for my application soon goes up to some 100 megabytes.
To find if the problem is not in my code, I commented away OnPropertyChanged calls. The memory did not go up and of course the chart did not display any data.
So I assume the problem is that the chart is not freeing the memory. The memory is not freed after I do _dataSlots[slotToClear] = null and the corresponding data line on the chart disappears, and also the memory does not return to normal after I completely close the WPF view where the chart is.
I tried even calling System.GC.Collect() after each dataSlots[slotToClear] = null but it does not help.
How can I force the WPF Toolkit chart to free the memory for data series which are not displayed any more?
In my example I have 1 chart with 365 points. The chart is defined in its own user control ChartView
. The main window looks so:
<Grid x:Name="root">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button x:Name="update" Content="Update first" Click="update_Click"/>
</StackPanel>
<local:ChartView Grid.Row="1" />
</Grid>
The event handler of the button:
private void update_Click(object sender, RoutedEventArgs e)
{
this.root.Children.RemoveAt(1);
GC.Collect();
this.model._dataSlots[0] = myDataProvider.GetPoints(); //this.DataContext = this.model
var v = new ChartView();
Grid.SetRow(v, 1);
this.root.Children.Insert(1, v);
}
The sequence is following:
- Remove the
ChartView
control from the visual tree. - Call the Garbage Collector.
- Update the view model.
- Insert new
ChartView
control.
After the start the application consumes 26Mb of memory. First update - 32Mb. Second update - 35Mb.
But next updates will not exceed this value, it is the maximum.
With 3650 point (10 times more) the numbers are: 52 -> 68 -> 88.
I don't know what will happens if to use 10 lines, but memory consumption must be any lower than 100Mb.
精彩评论