Why menu makes the CPU usage gets high?

Copper Contributor

Hi experts, in my wpf application, I have a datagrid with 100 columns, and there's a data updating thread to update all datagrid cell binding data every 1 second.

 

The cpu usage will be about 15% on my "slow" computer, but if I've popup a datagrid context menu or a top menu, the cpu usage will be up to 30%, and it won't get down any more even though I've close the menu.

 

And if I've suspended the data updating thread, the CPU usage get down to 0%, resume the data updating thread, the CPU usage get up to 30% again.

 

I've cut down the number of columns to 20, and the CPU usage goes up too but not so obviousely.

 

I've try build the project with .net framework 4.x, .net core 3.x, .net 5, .net 6, debug or release, the cpu usage will get up and won't get down any way.

 

I've try to set the context menu to null and do the garbage collection, but it makes no difference.

 

Really wanted to know why the CPU uasge gets high and how to make the number get down ?

 

Here is my source code, it's simple but a little bit long.

 

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;

namespace datagrid_perf_simple
{
    public class PriceAll
    {
        private double[] arr_ = new double[100];
        
        public PriceAll(double d)
        {
            for (int i = 0; i < 100; i++)
            {
                arr_[i] = d;
            }
        }

        public void UpdatePrice()
        {
            for (int i = 0; i < 100; i++)
            {
                arr_[i] += 0.001;
            }
        }
        public double Price0 => arr_[0];
        public double Price1 => arr_[1];
        public double Price2 => arr_[2];
        public double Price3 => arr_[3];
        public double Price4 => arr_[4];
        public double Price5 => arr_[5];
        public double Price6 => arr_[6];
        public double Price7 => arr_[7];
        public double Price8 => arr_[8];
        public double Price9 => arr_[9];
        public double Price10 => arr_[10];
        public double Price11 => arr_[11];
        public double Price12 => arr_[12];
        public double Price13 => arr_[13];
        public double Price14 => arr_[14];
        public double Price15 => arr_[15];
        public double Price16 => arr_[16];
        public double Price17 => arr_[17];
        public double Price18 => arr_[18];
        public double Price19 => arr_[19];
        public double Price20 => arr_[20];
        public double Price21 => arr_[21];
        public double Price22 => arr_[22];
        public double Price23 => arr_[23];
        public double Price24 => arr_[24];
        public double Price25 => arr_[25];
        public double Price26 => arr_[26];
        public double Price27 => arr_[27];
        public double Price28 => arr_[28];
        public double Price29 => arr_[29];
        public double Price30 => arr_[30];
        public double Price31 => arr_[31];
        public double Price32 => arr_[32];
        public double Price33 => arr_[33];
        public double Price34 => arr_[34];
        public double Price35 => arr_[35];
        public double Price36 => arr_[36];
        public double Price37 => arr_[37];
        public double Price38 => arr_[38];
        public double Price39 => arr_[39];
        public double Price40 => arr_[40];
        public double Price41 => arr_[41];
        public double Price42 => arr_[42];
        public double Price43 => arr_[43];
        public double Price44 => arr_[44];
        public double Price45 => arr_[45];
        public double Price46 => arr_[46];
        public double Price47 => arr_[47];
        public double Price48 => arr_[48];
        public double Price49 => arr_[49];
        public double Price50 => arr_[50];
        public double Price51 => arr_[51];
        public double Price52 => arr_[52];
        public double Price53 => arr_[53];
        public double Price54 => arr_[54];
        public double Price55 => arr_[55];
        public double Price56 => arr_[56];
        public double Price57 => arr_[57];
        public double Price58 => arr_[58];
        public double Price59 => arr_[59];
        public double Price60 => arr_[60];
        public double Price61 => arr_[61];
        public double Price62 => arr_[62];
        public double Price63 => arr_[63];
        public double Price64 => arr_[64];
        public double Price65 => arr_[65];
        public double Price66 => arr_[66];
        public double Price67 => arr_[67];
        public double Price68 => arr_[68];
        public double Price69 => arr_[69];
        public double Price70 => arr_[70];
        public double Price71 => arr_[71];
        public double Price72 => arr_[72];
        public double Price73 => arr_[73];
        public double Price74 => arr_[74];
        public double Price75 => arr_[75];
        public double Price76 => arr_[76];
        public double Price77 => arr_[77];
        public double Price78 => arr_[78];
        public double Price79 => arr_[79];
        public double Price80 => arr_[80];
        public double Price81 => arr_[81];
        public double Price82 => arr_[82];
        public double Price83 => arr_[83];
        public double Price84 => arr_[84];
        public double Price85 => arr_[85];
        public double Price86 => arr_[86];
        public double Price87 => arr_[87];
        public double Price88 => arr_[88];
        public double Price89 => arr_[89];
        public double Price90 => arr_[90];
        public double Price91 => arr_[91];
        public double Price92 => arr_[92];
        public double Price93 => arr_[93];
        public double Price94 => arr_[94];
        public double Price95 => arr_[95];
        public double Price96 => arr_[96];
        public double Price97 => arr_[97];
        public double Price98 => arr_[98];
        public double Price99 => arr_[99];
    }

    public class TestItem : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string s)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(s));
        }

        public PriceAll Pa { get; set; }

    }

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private DateTime lastUpdateTime_, lastChangeTime_;
        private bool closeFlag_ = false;
        private bool suspendFlag_ = false;
        public ObservableCollection<TestItem> testItems_ = new ObservableCollection<TestItem>();
        public ObservableCollection<TestItem> TestItems => testItems_;

        public MainWindow()
        {
            InitializeComponent();

            this.DataContext = this;

            for (int i = 0; i < 100; i++)
            {
                var item = new TestItem();
                item.Pa = new PriceAll(1.234);
                TestItems.Add(item);
            }

            if (true)
            {
                var t = new System.Threading.Thread(() =>
                {
                    for (int i = 1; i < 100000; ++i)
                    {
                        System.Threading.Thread.Sleep(100);
                        if (suspendFlag_)
                        {
                            continue;
                        }
                        if (closeFlag_)
                        {
                            break;
                        }
                        lock (this)
                        {
                            foreach (var item in TestItems)
                            {
                                for (int j = 0; j < 100; j++)
                                {
                                    item.Pa.UpdatePrice();
                                }
                                //item.OnPropertyChanged("Pa");
                            }
                            lastChangeTime_ = DateTime.Now;
                        }
                    }
                });
                t.Start();
            }

            if (true)
            {
                var t = new System.Threading.Thread(() =>
                {
                    for (; ; )
                    {
                        System.Threading.Thread.Sleep(1000);
                        if (suspendFlag_)
                        {
                            continue;
                        }
                        if (closeFlag_)
                        {
                            break;
                        }
                        lock (this)
                        {
                            if (lastChangeTime_ > lastUpdateTime_)
                            {
                                lastUpdateTime_ = lastChangeTime_;
                                foreach (var item in TestItems)
                                {
                                    item.OnPropertyChanged("Pa");
                                }
                            }
                        }
                    }
                });
                t.Start();
            }
        }

        private void testGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (sender == this.testGrid && testGrid.SelectedCells.Count == 1)
            {
                var col = testGrid.SelectedCells[0].Column;
            }
        }

        private void Window_Closing(object sender, CancelEventArgs e)
        {
            closeFlag_ = true;
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            //this.testGrid.ContextMenu = null;
            //this.testGrid.ContextMenu.IsEnabled = false;
        }

        private void testGrid_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            //if (this.testGrid.ContextMenu == null)
            //{
            //    var contextMenu = new ContextMenu();
            //    var item = new MenuItem();
            //    item.Header = "Plot time series chart";
            //    item.Click += new RoutedEventHandler(MenuItem_Click);
            //    contextMenu.Items.Add(item);

            //    //contextMenu.IsOpen = true;
            //    this.testGrid.ContextMenu = contextMenu;
            //}
        }

        private void BtnSuspend_Click(object sender, RoutedEventArgs e)
        {
            if (this.btnSuspend.Content as string == "Suspend")
            {
                this.btnSuspend.Content = "Run";
                this.suspendFlag_ = true;
            }
            else
            {
                this.btnSuspend.Content = "Suspend";
                this.suspendFlag_ = false;
            }
        }

        private void miExit_Click(object sender, RoutedEventArgs e)
        {
        }

        private void BtnGc_Click(object sender, RoutedEventArgs e)
        {
            GC.Collect();
        }
    }
}

 

 

 

<Window x:Class="datagrid_perf_simple.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:datagrid_perf_simple"
        mc:Ignorable="d" Title="MainWindow" Height="450" Width="800" Closing="Window_Closing">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="30" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Menu Grid.Row="0" x:Name="menu" HorizontalAlignment="Left" VerticalAlignment="Top" IsMainMenu="True">
            <MenuItem Header="File">
                <MenuItem x:Name="miExit" Header="Exit" Click="miExit_Click"></MenuItem>
            </MenuItem>
        </Menu>
        <StackPanel Grid.Row="1" Orientation="Horizontal">
            <Button x:Name="btnGc" Content="GC" Click="BtnGc_Click" />
            <Button x:Name="btnSuspend" Content="Suspend" Click="BtnSuspend_Click" />
        </StackPanel>
        <DataGrid Grid.Row="2" x:Name="testGrid" ItemsSource="{Binding TestItems}" 
                  SelectionUnit="Cell" IsReadOnly="True" AutoGenerateColumns="False" 
                  MouseDoubleClick="testGrid_MouseDoubleClick" Visibility="Visible" Margin="0" 
                  AlternatingRowBackground="LightCyan" FontSize="13" MouseRightButtonUp="testGrid_MouseRightButtonUp">
            <DataGrid.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Plot time series chart" Click="MenuItem_Click" />
                </ContextMenu>
            </DataGrid.ContextMenu>
            <DataGrid.Columns>
                <DataGridTextColumn Header="price0" Binding="{Binding Pa.Price0, Mode=OneWay}" />
                <DataGridTextColumn Header="price1" Binding="{Binding Pa.Price1, Mode=OneWay}" />
                <DataGridTextColumn Header="price2" Binding="{Binding Pa.Price2, Mode=OneWay}" />
                <DataGridTextColumn Header="price3" Binding="{Binding Pa.Price3, Mode=OneWay}" />
                <DataGridTextColumn Header="price4" Binding="{Binding Pa.Price4, Mode=OneWay}" />
                <DataGridTextColumn Header="price5" Binding="{Binding Pa.Price5, Mode=OneWay}" />
                <DataGridTextColumn Header="price6" Binding="{Binding Pa.Price6, Mode=OneWay}" />
                <DataGridTextColumn Header="price7" Binding="{Binding Pa.Price7, Mode=OneWay}" />
                <DataGridTextColumn Header="price8" Binding="{Binding Pa.Price8, Mode=OneWay}" />
                <DataGridTextColumn Header="price9" Binding="{Binding Pa.Price9, Mode=OneWay}" />
                <DataGridTextColumn Header="price10" Binding="{Binding Pa.Price10, Mode=OneWay}" />
                <DataGridTextColumn Header="price11" Binding="{Binding Pa.Price11, Mode=OneWay}" />
                <DataGridTextColumn Header="price12" Binding="{Binding Pa.Price12, Mode=OneWay}" />
                <DataGridTextColumn Header="price13" Binding="{Binding Pa.Price13, Mode=OneWay}" />
                <DataGridTextColumn Header="price14" Binding="{Binding Pa.Price14, Mode=OneWay}" />
                <DataGridTextColumn Header="price15" Binding="{Binding Pa.Price15, Mode=OneWay}" />
                <DataGridTextColumn Header="price16" Binding="{Binding Pa.Price16, Mode=OneWay}" />
                <DataGridTextColumn Header="price17" Binding="{Binding Pa.Price17, Mode=OneWay}" />
                <DataGridTextColumn Header="price18" Binding="{Binding Pa.Price18, Mode=OneWay}" />
                <DataGridTextColumn Header="price19" Binding="{Binding Pa.Price19, Mode=OneWay}" />
                <DataGridTextColumn Header="price20" Binding="{Binding Pa.Price20, Mode=OneWay}" />
                <DataGridTextColumn Header="price21" Binding="{Binding Pa.Price21, Mode=OneWay}" />
                <DataGridTextColumn Header="price22" Binding="{Binding Pa.Price22, Mode=OneWay}" />
                <DataGridTextColumn Header="price23" Binding="{Binding Pa.Price23, Mode=OneWay}" />
                <DataGridTextColumn Header="price24" Binding="{Binding Pa.Price24, Mode=OneWay}" />
                <DataGridTextColumn Header="price25" Binding="{Binding Pa.Price25, Mode=OneWay}" />
                <DataGridTextColumn Header="price26" Binding="{Binding Pa.Price26, Mode=OneWay}" />
                <DataGridTextColumn Header="price27" Binding="{Binding Pa.Price27, Mode=OneWay}" />
                <DataGridTextColumn Header="price28" Binding="{Binding Pa.Price28, Mode=OneWay}" />
                <DataGridTextColumn Header="price29" Binding="{Binding Pa.Price29, Mode=OneWay}" />
                <DataGridTextColumn Header="price30" Binding="{Binding Pa.Price30, Mode=OneWay}" />
                <DataGridTextColumn Header="price31" Binding="{Binding Pa.Price31, Mode=OneWay}" />
                <DataGridTextColumn Header="price32" Binding="{Binding Pa.Price32, Mode=OneWay}" />
                <DataGridTextColumn Header="price33" Binding="{Binding Pa.Price33, Mode=OneWay}" />
                <DataGridTextColumn Header="price34" Binding="{Binding Pa.Price34, Mode=OneWay}" />
                <DataGridTextColumn Header="price35" Binding="{Binding Pa.Price35, Mode=OneWay}" />
                <DataGridTextColumn Header="price36" Binding="{Binding Pa.Price36, Mode=OneWay}" />
                <DataGridTextColumn Header="price37" Binding="{Binding Pa.Price37, Mode=OneWay}" />
                <DataGridTextColumn Header="price38" Binding="{Binding Pa.Price38, Mode=OneWay}" />
                <DataGridTextColumn Header="price39" Binding="{Binding Pa.Price39, Mode=OneWay}" />
                <DataGridTextColumn Header="price40" Binding="{Binding Pa.Price40, Mode=OneWay}" />
                <DataGridTextColumn Header="price41" Binding="{Binding Pa.Price41, Mode=OneWay}" />
                <DataGridTextColumn Header="price42" Binding="{Binding Pa.Price42, Mode=OneWay}" />
                <DataGridTextColumn Header="price43" Binding="{Binding Pa.Price43, Mode=OneWay}" />
                <DataGridTextColumn Header="price44" Binding="{Binding Pa.Price44, Mode=OneWay}" />
                <DataGridTextColumn Header="price45" Binding="{Binding Pa.Price45, Mode=OneWay}" />
                <DataGridTextColumn Header="price46" Binding="{Binding Pa.Price46, Mode=OneWay}" />
                <DataGridTextColumn Header="price47" Binding="{Binding Pa.Price47, Mode=OneWay}" />
                <DataGridTextColumn Header="price48" Binding="{Binding Pa.Price48, Mode=OneWay}" />
                <DataGridTextColumn Header="price49" Binding="{Binding Pa.Price49, Mode=OneWay}" />
                <DataGridTextColumn Header="price50" Binding="{Binding Pa.Price50, Mode=OneWay}" />
                <DataGridTextColumn Header="price51" Binding="{Binding Pa.Price51, Mode=OneWay}" />
                <DataGridTextColumn Header="price52" Binding="{Binding Pa.Price52, Mode=OneWay}" />
                <DataGridTextColumn Header="price53" Binding="{Binding Pa.Price53, Mode=OneWay}" />
                <DataGridTextColumn Header="price54" Binding="{Binding Pa.Price54, Mode=OneWay}" />
                <DataGridTextColumn Header="price55" Binding="{Binding Pa.Price55, Mode=OneWay}" />
                <DataGridTextColumn Header="price56" Binding="{Binding Pa.Price56, Mode=OneWay}" />
                <DataGridTextColumn Header="price57" Binding="{Binding Pa.Price57, Mode=OneWay}" />
                <DataGridTextColumn Header="price58" Binding="{Binding Pa.Price58, Mode=OneWay}" />
                <DataGridTextColumn Header="price59" Binding="{Binding Pa.Price59, Mode=OneWay}" />
                <DataGridTextColumn Header="price60" Binding="{Binding Pa.Price60, Mode=OneWay}" />
                <DataGridTextColumn Header="price61" Binding="{Binding Pa.Price61, Mode=OneWay}" />
                <DataGridTextColumn Header="price62" Binding="{Binding Pa.Price62, Mode=OneWay}" />
                <DataGridTextColumn Header="price63" Binding="{Binding Pa.Price63, Mode=OneWay}" />
                <DataGridTextColumn Header="price64" Binding="{Binding Pa.Price64, Mode=OneWay}" />
                <DataGridTextColumn Header="price65" Binding="{Binding Pa.Price65, Mode=OneWay}" />
                <DataGridTextColumn Header="price66" Binding="{Binding Pa.Price66, Mode=OneWay}" />
                <DataGridTextColumn Header="price67" Binding="{Binding Pa.Price67, Mode=OneWay}" />
                <DataGridTextColumn Header="price68" Binding="{Binding Pa.Price68, Mode=OneWay}" />
                <DataGridTextColumn Header="price69" Binding="{Binding Pa.Price69, Mode=OneWay}" />
                <DataGridTextColumn Header="price70" Binding="{Binding Pa.Price70, Mode=OneWay}" />
                <DataGridTextColumn Header="price71" Binding="{Binding Pa.Price71, Mode=OneWay}" />
                <DataGridTextColumn Header="price72" Binding="{Binding Pa.Price72, Mode=OneWay}" />
                <DataGridTextColumn Header="price73" Binding="{Binding Pa.Price73, Mode=OneWay}" />
                <DataGridTextColumn Header="price74" Binding="{Binding Pa.Price74, Mode=OneWay}" />
                <DataGridTextColumn Header="price75" Binding="{Binding Pa.Price75, Mode=OneWay}" />
                <DataGridTextColumn Header="price76" Binding="{Binding Pa.Price76, Mode=OneWay}" />
                <DataGridTextColumn Header="price77" Binding="{Binding Pa.Price77, Mode=OneWay}" />
                <DataGridTextColumn Header="price78" Binding="{Binding Pa.Price78, Mode=OneWay}" />
                <DataGridTextColumn Header="price79" Binding="{Binding Pa.Price79, Mode=OneWay}" />
                <DataGridTextColumn Header="price80" Binding="{Binding Pa.Price80, Mode=OneWay}" />
                <DataGridTextColumn Header="price81" Binding="{Binding Pa.Price81, Mode=OneWay}" />
                <DataGridTextColumn Header="price82" Binding="{Binding Pa.Price82, Mode=OneWay}" />
                <DataGridTextColumn Header="price83" Binding="{Binding Pa.Price83, Mode=OneWay}" />
                <DataGridTextColumn Header="price84" Binding="{Binding Pa.Price84, Mode=OneWay}" />
                <DataGridTextColumn Header="price85" Binding="{Binding Pa.Price85, Mode=OneWay}" />
                <DataGridTextColumn Header="price86" Binding="{Binding Pa.Price86, Mode=OneWay}" />
                <DataGridTextColumn Header="price87" Binding="{Binding Pa.Price87, Mode=OneWay}" />
                <DataGridTextColumn Header="price88" Binding="{Binding Pa.Price88, Mode=OneWay}" />
                <DataGridTextColumn Header="price89" Binding="{Binding Pa.Price89, Mode=OneWay}" />
                <DataGridTextColumn Header="price90" Binding="{Binding Pa.Price90, Mode=OneWay}" />
                <DataGridTextColumn Header="price91" Binding="{Binding Pa.Price91, Mode=OneWay}" />
                <DataGridTextColumn Header="price92" Binding="{Binding Pa.Price92, Mode=OneWay}" />
                <DataGridTextColumn Header="price93" Binding="{Binding Pa.Price93, Mode=OneWay}" />
                <DataGridTextColumn Header="price94" Binding="{Binding Pa.Price94, Mode=OneWay}" />
                <DataGridTextColumn Header="price95" Binding="{Binding Pa.Price95, Mode=OneWay}" />
                <DataGridTextColumn Header="price96" Binding="{Binding Pa.Price96, Mode=OneWay}" />
                <DataGridTextColumn Header="price97" Binding="{Binding Pa.Price97, Mode=OneWay}" />
                <DataGridTextColumn Header="price98" Binding="{Binding Pa.Price98, Mode=OneWay}" />
                <DataGridTextColumn Header="price99" Binding="{Binding Pa.Price99, Mode=OneWay}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

 

1 Reply

Hi @GuoshengWei,

Thanks for posting your issue here.

However this platform is used for how-to discussions and sharing best practices for building any app with .NET.Since your issue is a technical question, welcome to post it in Microsoft Q&A forum, the support team and communities on Microsoft Q&A will help you for any technical questions.
Besides, it will be appreciated if you can share it here once you post this technical question Microsoft Q&A.
Best Regards,
Lan Huang