当我添加这么多图表时,Oxyplot抛出异常

问题描述 投票:0回答:1

我想用OxyPlot库挖出这么多图表。

我现在正在测试我可以用动态添加多少个图形(但是我不会在10000个图形上添加图形,因为它是实际应用中的最大图形)。

但是,当我添加200多个图形时,Oxyplot抛出异常。

异常消息是“此PlotModel已被其他一些PlotView控件使用。”。

我的所有代码都有。 (在代码中,我添加了带动态的图形,并且我在其他线程中每5秒向所有图形添加值。)

// Xaml - MainView

<Window x:Class="OxyplotStressTest.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:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
    xmlns:local="clr-namespace:OxyplotStressTest"
    mc:Ignorable="d"
    Title="MainWindow" Height="550" Width="725">
<Grid>
    <Button Content="Add 100" HorizontalAlignment="Left" Height="32" Margin="20,23,0,0" VerticalAlignment="Top" Width="65" Click="Button_Click100"/>
    <Button Content="Add 50" HorizontalAlignment="Left" Height="32" Margin="102,23,0,0" VerticalAlignment="Top" Width="65" Click="Button_Click50"/>
    <Button Content="Add 10" HorizontalAlignment="Left" Height="32" Margin="189,23,0,0" VerticalAlignment="Top" Width="65" Click="Button_Click10"/>
    <Button Content="Add 1" HorizontalAlignment="Left" Height="32" Margin="274,23,0,0" VerticalAlignment="Top" Width="65" Click="Button_Click1"/>

    <Grid Margin="20,65,19,10">
        <ScrollViewer>
            <ItemsControl ItemsSource="{Binding List}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <Label Content="{Binding Tag}"/>
                            <oxy:PlotView HorizontalAlignment="Left" Height="130" Margin="20,23,0,0" VerticalAlignment="Top" Width="600" 
                      Model="{Binding Chart}" IsMouseWheelEnabled="False" IsManipulationEnabled="False" />
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
    </Grid>
</Grid>

// C# - MainWindow.cs

public partial class MainWindow : Window
{
    private MainWindowViewModel mMainWindowViewModel = null;

    public MainWindow()
    {
        InitializeComponent();
        MainWindowViewModel mainWindowViewModel = new MainWindowViewModel();
        this.DataContext = mainWindowViewModel;
        mMainWindowViewModel = mainWindowViewModel;
        Thread thread = new Thread(new ParameterizedThreadStart(reloadGraph));
        thread.Start();
    }

    private void Button_Click100(object sender, RoutedEventArgs e)
    {
        AddGraph addGraph = new AddGraph(mMainWindowViewModel);
        addGraph.addGraph(100);
    }

    private void Button_Click50(object sender, RoutedEventArgs e)
    {
        AddGraph addGraph = new AddGraph(mMainWindowViewModel);
        addGraph.addGraph(50);
    }

    private void Button_Click10(object sender, RoutedEventArgs e)
    {
        AddGraph addGraph = new AddGraph(mMainWindowViewModel);
        addGraph.addGraph(10);
    }

    private void Button_Click1(object sender, RoutedEventArgs e)
    {
        AddGraph addGraph = new AddGraph(mMainWindowViewModel);
        addGraph.addGraph(1);
    }

    private void reloadGraph(object param)
    {
        while (true)
        {
            Thread.Sleep(5000);

            if (mMainWindowViewModel.List.Count > 0)
            {
                AddGraph addGraph = new AddGraph(mMainWindowViewModel);
                addGraph.reloadGraph();
            }

            Console.WriteLine(Environment.WorkingSet.ToString());
        }
    }
}

// C# - MainViewModel

    public MainWindowViewModel()
    {
        listVal = new ObservableCollection<Items>();
        BindingOperations.EnableCollectionSynchronization(this.listVal, new object());
    }


    private ObservableCollection<Items> listVal = new ObservableCollection<Items>();
    public ObservableCollection<Items> List
    {
        get
        {
            return listVal;
        }
        set
        {
            listVal = value;
            NotifyPropertyChanged("List");
        }
    }


public class Items
{
    public string Tag { get; set; }
    private PlotModel chartVal = new PlotModel();
    public PlotModel Chart
    {
        get
        {
            return chartVal;
        }
        set
        {
            chartVal = value;
        }
    }
}


public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
} 

// C# - 模型类

class AddGraph
{
    private MainWindowViewModel mMainWindowViewModel = null;

    public AddGraph(MainWindowViewModel pMainWindowViewModel)
    {
        mMainWindowViewModel = pMainWindowViewModel;
    }

    public void addGraph(int pCount)
    {
        try
        {
            for (int i = 0; i < pCount; i++)
            {
                Random random = new Random();
                long data = random.Next(100);

                ColumnSeries column = new ColumnSeries();
                column.FillColor = OxyColors.SkyBlue;
                column.Items.Add(new ColumnItem() { Value = data });
                data *= random.Next(50);
                column.Items.Add(new ColumnItem() { Value = data });

                Items items = new Items();
                items.Tag = mMainWindowViewModel.List.Count.ToString();
                items.Chart.Series.Add(column);
                items.Chart.InvalidatePlot(true);

                mMainWindowViewModel.List.Add(items);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }



    public void reloadGraph()
    {
        try
        {
            List<Items> newList = new List<Items>();

            foreach (Items listItem in mMainWindowViewModel.List)
            {
                string tag = listItem.Tag;
                PlotModel plotModel = listItem.Chart;

                ColumnSeries oldGraph = (ColumnSeries)plotModel.Series[0];

                ColumnSeries newGraph = new ColumnSeries();
                newGraph.FillColor = OxyColors.SkyBlue;

                for (int i = 0; i < oldGraph.Items.Count; i++)
                {
                    if (oldGraph.Items.Count == 30 && i == 0)
                    {
                        continue;
                    }

                    newGraph.Items.Add(new ColumnItem() { Value = oldGraph.Items[i].Value });
                }

                Random random = new Random();
                long val = random.Next(500);
                val *= random.Next(50);

                newGraph.Items.Add(new ColumnItem() { Value = val });

                Items items = new Items();
                items.Tag = tag;
                items.Chart.Series.Add(newGraph);
                items.Chart.InvalidatePlot(true);

                newList.Add(items);
            }
#region   //there are my solution and it shows good performance
            int index = 0;

            foreach (var addItem in newList)
            {
                mMainWindowViewModel.List[index] = addItem;
                index++;
            }
#endregion

#region  //there are my first code and it has problem
            mMainWindowViewModel.List.Clear();

            foreach (var addItem in newList)
            {
                mMainWindowViewModel.List.Add(addItem);
            }
#endregion
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

也许我的代码很糟糕,但我不知道坏代码在哪里,因为它不会在BreakPoint上停止。

如果你给我一个建议,我很高兴。

c# wpf oxyplot
1个回答
0
投票

我想你可能需要使用OxyPlot例子中的想法来重建它:https://github.com/oxyplot/oxyplot/tree/develop/Source/Examples/WPF/WpfExamples

当我上个月使用oxyplots工作时,我发现这个官方示例很好地完成了他们的想法,他们使用此虚拟化的Performance Demo解决方案可能有助于提高性能:

            <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel IsVirtualizing="True" IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

问题可能导致使用NotifyPropertyChange作为刷新UI,因为添加新图表可能应该以某种方式取消绑定列表>通知>绑定新列表。

检查链接中的更多内容,并尝试混搭他们的解决方案,让自己的:)我很高兴,如果我帮助了一些:)

© www.soinside.com 2019 - 2024. All rights reserved.