Oxyplot выдает исключение, когда я добавляю так много графиков - PullRequest
0 голосов
/ 15 марта 2019

Я хочу нарисовать так много графиков с помощью библиотеки 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.

Если вы дадите мне совет, я так рад.

1 Ответ

0 голосов
/ 23 марта 2019

Я думаю, что вам, возможно, придется немного перестроить его, используя идею из OxyPlot Пример: https://github.com/oxyplot/oxyplot/tree/develop/Source/Examples/WPF/WpfExamples

Когда я работал в последние месяцы с оксиплотами, я обнаружил, что эти официальные примеры хорошо сделаны с их идеями,Решение с демонстрацией производительности с использованием этой виртуализации может помочь с производительностью:

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

Проблема может быть связана с использованием NotifyPropertyChange в качестве обновляющего интерфейса пользователя при добавлении новой диаграммы, возможно, вам следует каким-то образом отменить привязку списка> Уведомить> Привязать новый список.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *,, 1008 *, проверьте больше по ссылке и попробуйте сделать решение, чтобы сделать свое собственное :).
...