Commit f0c92ba3 authored by Rabbit's avatar Rabbit
Browse files

极限性能优化,15个标签直接从30%CPU占用率降低到2%

parent 06939d33
Loading
Loading
Loading
Loading
+351 −204
Original line number Diff line number Diff line
#pragma warning disable CA1416, CS8602
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Diagnostics.Metrics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Xml.Linq;
using System.Windows.Threading;
using CountDownList.Controls;
using CountDownList.UI.Window;
using HandyControl.Controls;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;

namespace CountDownList.Class
@@ -30,10 +19,17 @@ namespace CountDownList.Class
        public VirtualizingStackPanel DoingPanel , WcPanel, CountPanel;
        public Expander DoingE, WcE, CountE;
        public FrameworkElement RootWindow;
        public MyScrollViewer ScrollViewer;

        NotifyCore notifyCore = new();

        public bool IsOpen = true;

        private DispatcherTimer _visibleTimer;   // 可见标签定时器(35FPS ≈ 28.5ms)
        private DispatcherTimer _hiddenTimer;    // 不可见标签定时器(5FPS = 200ms)
        private HashSet<ListLabel> _visibleLabels = new();
        private HashSet<ListLabel> _hiddenLabels = new();

        public ListCore
        (
            VirtualizingStackPanel doingPanel,
@@ -42,7 +38,8 @@ namespace CountDownList.Class
            Expander doingE,
            Expander wcE,
            Expander countE,
            FrameworkElement Window
            FrameworkElement Window,
            MyScrollViewer scrollViewer
        )
        {
            App.logFile.Info("开始初始化", className);
@@ -53,11 +50,151 @@ namespace CountDownList.Class
            WcE = wcE;
            CountE = countE;
            RootWindow = Window;
            ScrollViewer = scrollViewer;

            RefreshNumber();
            //HookPanelChanges();
            InitTimers(); // 确保调用
            HookScrollEvents();

            App.logFile.Info("初始化结束", className);
        }

        private Rect _currentViewport;
        private void HookScrollEvents()
        {
            if (RootWindow is ScrollViewer scrollViewer)
            {
                scrollViewer.ScrollChanged += (s, e) =>
                {
                    // 计算当前视口范围
                    _currentViewport = new Rect(
                        e.HorizontalOffset,
                        e.VerticalOffset,
                        e.ViewportWidth,
                        e.ViewportHeight
                    );
                };
            }
        }
        private void UpdateLabelVisibility()
        {
            _visibleLabels.Clear();
            _hiddenLabels.Clear();

            void ClassifyPanel(VirtualizingStackPanel panel, Expander expander)
            {
                if (!expander.IsExpanded || !IsOpen) return;

                foreach (ListLabel lb in panel.Children.OfType<ListLabel>())
                {
                    if (IsUserVisible(lb, RootWindow))
                        _visibleLabels.Add(lb);
                    else
                        _hiddenLabels.Add(lb);
                }
            }

            ClassifyPanel(DoingPanel, DoingE);
            ClassifyPanel(WcPanel, WcE);
            ClassifyPanel(CountPanel, CountE);
        }

        private bool IsInViewport(FrameworkElement element)
        {
            // 获取元素相对于ScrollViewer的位置
            GeneralTransform transform = element.TransformToAncestor(RootWindow);
            Rect bounds = transform.TransformBounds(new Rect(0, 0, element.ActualWidth, element.ActualHeight));

            // 判断是否在视口内
            return _currentViewport.IntersectsWith(bounds);
        }

        private DateTime _lastUpdateTime;

        private void InitTimers()
        {
            // 可见标签定时器(35FPS)
            _visibleTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(28.57) };
            _visibleTimer.Tick += (s, e) => UpdateVisibleLabels();

            // 不可见标签定时器(5FPS)
            _hiddenTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(200) };
            _hiddenTimer.Tick += (s, e) => UpdateHiddenLabels();

            _visibleTimer.Start();
            _hiddenTimer.Start();
        }

        public void HookEvents()
        {
            if (RootWindow is ScrollViewer scrollViewer)
            {
                scrollViewer.ScrollChanged += (s, e) => UpdateLabelVisibility();
            }

            DoingE.Expanded += (s, e) => UpdateLabelVisibility();
            WcE.Expanded += (s, e) => UpdateLabelVisibility();
            CountE.Expanded += (s, e) => UpdateLabelVisibility();
        }

        private void UpdateVisibleLabels()
        {
            foreach (var lb in _visibleLabels)
            {
                lb.SyncProgress();
                lb.SyncTime();
                lb.SyncTitle();
            }
        }

        private void UpdateHiddenLabels()
        {
            foreach (var lb in _hiddenLabels)
            {
                // 不可见标签仅更新必要属性(如进度超过阈值时)
                if (lb.Progress < 5) // 示例:进度小于5%时跳过更新
                {
                    lb.SyncProgress();
                }
            }
        }

        //private void UpdateVisibleLabels()
        //{
        //    _activeLabels.Clear();

        //    void ProcessPanel(VirtualizingStackPanel panel, Expander expander)
        //    {
        //        if (!expander.IsExpanded || !IsOpen) return;

        //        foreach (ListLabel lb in panel.Children.OfType<ListLabel>())
        //        {
        //            // 如果缓存中存在,直接使用缓存值
        //            if (_visibilityCache.TryGetValue(lb, out bool isVisible))
        //            {
        //                if (isVisible) _activeLabels.Add(lb);
        //            }
        //            // 如果缓存中不存在,重新计算并缓存
        //            else
        //            {
        //                bool visible = IsUserVisible(lb, RootWindow);
        //                _visibilityCache[lb] = visible;
        //                if (visible) _activeLabels.Add(lb);
        //            }
        //        }
        //    }

        //    ProcessPanel(DoingPanel, DoingE);
        //    ProcessPanel(WcPanel, WcE);
        //    ProcessPanel(CountPanel, CountE);

        //    foreach (var lb in _activeLabels)
        //    {
        //        lb.BatchUpdate(); // 替换原有的多个Sync调用
        //    }
        //}

        /// <summary>
        /// 刷新计数
        /// </summary>
@@ -115,70 +252,70 @@ namespace CountDownList.Class
                    DoingPanel.Children.Add(lb);
                }

                while (!lb.IsDelete)
                {
                    if (DateTime.Now <= et)
                    {
                        //当不是正计时时执行
                        //当展开框展开时才刷新控件,以优化性能

                        if (DoingE.IsExpanded && IsOpen)
                        {
                            if (IsUserVisible(lb, RootWindow))
                            {
                                lb.SyncProgress();
                                lb.SyncTime();
                                lb.SyncTitle();
                            }
                        }
                    }
                    else
                    {
                        //当不是正计时并且已完成
                        //完成时移入“已完成”
                        if (!Move)
                        {
                            Move = true;//运行一次

                            DoingPanel.Children.Remove(lb);//从进行中移除控件
                            WcPanel.Children.Add(lb);//添加到已完成

                            if (!IsUserVisible(lb, RootWindow))
                            {
                                await Task.Delay(250);
                            }

                            App.logFile.Info($"Label {t} 已移入“已完成”区域", className);
                        }

                        if (WcE.IsExpanded && IsOpen && IsUserVisible(lb, RootWindow))
                        {
                            if (IsUserVisible(lb, RootWindow))
                            {
                                //当展开框展开时才刷新控件,以优化性能
                                lb.SyncProgress();
                                lb.SyncTime();
                                lb.SyncTitle();
                            }
                        }
                    }

                    if (MiscSetting.Default.Pref)
                    {
                        if (lb.IsMouseEnter || lb.Open)
                        {
                            await Task.Delay(15);
                        }
                        else
                        {
                            await Task.Delay(75);
                        }
                    }
                    else
                    {
                        await Task.Delay(10);
                    }
                }
                //while (!lb.IsDelete)
                //{
                //    if (DateTime.Now <= et)
                //    {
                //        //当不是正计时时执行
                //        //当展开框展开时才刷新控件,以优化性能

                //        if (DoingE.IsExpanded && IsOpen)
                //        {
                //            if (IsUserVisible(lb, RootWindow))
                //            {
                //                lb.SyncProgress();
                //                lb.SyncTime();
                //                lb.SyncTitle();
                //            }
                //        }
                //    }
                //    else
                //    {
                //        //当不是正计时并且已完成
                //        //完成时移入“已完成”
                //        if (!Move)
                //        {
                //            Move = true;//运行一次

                //            DoingPanel.Children.Remove(lb);//从进行中移除控件
                //            WcPanel.Children.Add(lb);//添加到已完成

                //            if (!IsUserVisible(lb, RootWindow))
                //            {
                //                await Task.Delay(250);
                //            }

                //            App.logFile.Info($"Label {t} 已移入“已完成”区域", className);
                //        }

                //        if (WcE.IsExpanded && IsOpen && IsUserVisible(lb, RootWindow))
                //        {
                //            if (IsUserVisible(lb, RootWindow))
                //            {
                //                //当展开框展开时才刷新控件,以优化性能
                //                lb.SyncProgress();
                //                lb.SyncTime();
                //                lb.SyncTitle();
                //            }
                //        }
                //    }

                //    if (MiscSetting.Default.Pref)
                //    {
                //        if (lb.IsMouseEnter || lb.Open)
                //        {
                //            await Task.Delay(15);
                //        }
                //        else
                //        {
                //            await Task.Delay(75);
                //        }
                //    }
                //    else
                //    {
                //        await Task.Delay(10);
                //    }
                //}
            }
        }

@@ -217,72 +354,72 @@ namespace CountDownList.Class
                    DoingPanel.Children.Add(lb);
                }

                while (!lb.IsDelete)
                {
                    if (DateTime.Now <= lb.EndTime)
                    {
                        //当不是正计时时执行
                        //当展开框展开时才刷新控件,以优化性能

                        if (DoingE.IsExpanded && IsOpen)
                        {
                            if (IsUserVisible(lb, RootWindow))
                            {
                                lb.SyncProgress();
                                lb.SyncTime();
                                lb.SyncTitle();
                            }
                        }
                    }
                    else
                    {
                        //当不是正计时并且已完成
                        //完成时移入“已完成”
                        if (!Move)
                        {
                            Move = true;//运行一次

                            DoingPanel.Children.Remove(lb);//从进行中移除控件
                            WcPanel.Children.Add(lb);//添加到已完成

                            if (MiscSetting.Default.Pref)
                            {
                                if (!IsUserVisible(lb, RootWindow))
                                {
                                    await Task.Delay(250);
                                }
                            }
                            App.logFile.Info($"Label {label.Title} 已移入“已完成”区域", className);
                        }

                        if (WcE.IsExpanded && IsOpen && IsUserVisible(lb, RootWindow))
                        {
                            if (IsUserVisible(lb, RootWindow))
                            {
                                //当展开框展开时才刷新控件,以优化性能
                                lb.SyncProgress();
                                lb.SyncTime();
                                lb.SyncTitle();
                            }
                        }
                    }

                    if (MiscSetting.Default.Pref)
                    {
                        if (lb.IsMouseEnter || lb.Open)
                        {
                            await Task.Delay(15);
                        }
                        else
                        {
                            await Task.Delay(75);
                        }
                    }
                    else
                    {
                        await Task.Delay(10);
                    }
                }
                //while (!lb.IsDelete)
                //{
                //    if (DateTime.Now <= lb.EndTime)
                //    {
                //        //当不是正计时时执行
                //        //当展开框展开时才刷新控件,以优化性能

                //        if (DoingE.IsExpanded && IsOpen)
                //        {
                //            if (IsUserVisible(lb, RootWindow))
                //            {
                //                lb.SyncProgress();
                //                lb.SyncTime();
                //                lb.SyncTitle();
                //            }
                //        }
                //    }
                //    else
                //    {
                //        //当不是正计时并且已完成
                //        //完成时移入“已完成”
                //        if (!Move)
                //        {
                //            Move = true;//运行一次

                //            DoingPanel.Children.Remove(lb);//从进行中移除控件
                //            WcPanel.Children.Add(lb);//添加到已完成

                //            if (MiscSetting.Default.Pref)
                //            {
                //                if (!IsUserVisible(lb, RootWindow))
                //                {
                //                    await Task.Delay(250);
                //                }
                //            }
                //            App.logFile.Info($"Label {label.Title} 已移入“已完成”区域", className);
                //        }

                //        if (WcE.IsExpanded && IsOpen && IsUserVisible(lb, RootWindow))
                //        {
                //            if (IsUserVisible(lb, RootWindow))
                //            {
                //                //当展开框展开时才刷新控件,以优化性能
                //                lb.SyncProgress();
                //                lb.SyncTime();
                //                lb.SyncTitle();
                //            }
                //        }
                //    }

                //    if (MiscSetting.Default.Pref)
                //    {
                //        if (lb.IsMouseEnter || lb.Open)
                //        {
                //            await Task.Delay(15);
                //        }
                //        else
                //        {
                //            await Task.Delay(75);
                //        }
                //    }
                //    else
                //    {
                //        await Task.Delay(10);
                //    }
                //}
            }
        }

@@ -380,36 +517,36 @@ namespace CountDownList.Class
                }


                while (true)
                {
                    //当不是正计时时执行
                    //当展开框展开时才刷新控件,以优化性能
                    if (CountE.IsExpanded && IsOpen)
                    {
                        if (IsUserVisible(lb, RootWindow))
                        {
                            lb.SyncProgress();
                            lb.SyncTime();
                            lb.SyncTitle();
                        }
                    }

                    if (MiscSetting.Default.Pref)
                    {
                        if (lb.IsMouseEnter || lb.Open)
                        {
                            await Task.Delay(15);
                        }
                        else
                        {
                            await Task.Delay(75);
                        }
                    }
                    else
                    {
                        await Task.Delay(10);
                    }
                }
                //while (true)
                //{
                //    //当不是正计时时执行
                //    //当展开框展开时才刷新控件,以优化性能
                //    if (CountE.IsExpanded && IsOpen)
                //    {
                //        if (IsUserVisible(lb, RootWindow))
                //        {
                //            lb.SyncProgress();
                //            lb.SyncTime();
                //            lb.SyncTitle();
                //        }
                //    }

                //    if (MiscSetting.Default.Pref)
                //    {
                //        if (lb.IsMouseEnter || lb.Open)
                //        {
                //            await Task.Delay(15);
                //        }
                //        else
                //        {
                //            await Task.Delay(75);
                //        }
                //    }
                //    else
                //    {
                //        await Task.Delay(10);
                //    }
                //}
            }
        }

@@ -441,36 +578,36 @@ namespace CountDownList.Class
                }


                while (true)
                {
                    //当不是正计时时执行
                    //当展开框展开时才刷新控件,以优化性能
                    if (CountE.IsExpanded && IsOpen)
                    {
                        if (IsUserVisible(lb, RootWindow))
                        {
                            lb.SyncProgress();
                            lb.SyncTime();
                            lb.SyncTitle();
                        }
                    }

                    if (MiscSetting.Default.Pref)
                    {
                        if (lb.IsMouseEnter || lb.Open)
                        {
                            await Task.Delay(15);
                        }
                        else
                        {
                            await Task.Delay(75);
                        }
                    }
                    else
                    {
                        await Task.Delay(10);
                    }
                }
                //while (true)
                //{
                //    //当不是正计时时执行
                //    //当展开框展开时才刷新控件,以优化性能
                //    if (CountE.IsExpanded && IsOpen)
                //    {
                //        if (IsUserVisible(lb, RootWindow))
                //        {
                //            lb.SyncProgress();
                //            lb.SyncTime();
                //            lb.SyncTitle();
                //        }
                //    }

                //    if (MiscSetting.Default.Pref)
                //    {
                //        if (lb.IsMouseEnter || lb.Open)
                //        {
                //            await Task.Delay(15);
                //        }
                //        else
                //        {
                //            await Task.Delay(75);
                //        }
                //    }
                //    else
                //    {
                //        await Task.Delay(10);
                //    }
                //}
            }
        }

@@ -515,7 +652,12 @@ namespace CountDownList.Class
            DoingPanel.Children.Remove(element);
            WcPanel.Children.Remove(element);
            CountPanel.Children.Remove(element);
            App.logFile.Info($"已删除“{element.Title}”", className);

            // 从缓存中移除
            if (_visibilityCache.ContainsKey(element))
            {
                _visibilityCache.Remove(element);
            }
        }

        public List<ListLabel> ScanToCollection()
@@ -927,6 +1069,9 @@ namespace CountDownList.Class
            }
        }

        // 存储标签的可见性状态(Key: ListLabel, Value: 是否可见)
        private Dictionary<ListLabel, bool> _visibilityCache = new();
        
        /// <summary>
        /// 控件是否在窗口上显示,代码来自 https://cloud.tencent.com/developer/ask/sof/116724
        /// </summary>
@@ -1069,6 +1214,8 @@ namespace CountDownList.Class
                return notFoundReturn;
            }
        }


    }

    public enum ExtraMode
+23 −10
Original line number Diff line number Diff line
@@ -95,16 +95,6 @@ namespace CountDownList.Controls

        public void Dispose()
        {
            App.logFile.Info($"触发销毁ListLabel({Title})", className);

            IsStop = true;
            // 解除所有绑定
            BindingOperations.ClearAllBindings(this);

            // 解除事件处理程序
            this.Unloaded -= Button_Click;

            GC.Collect();
            GC.SuppressFinalize(this);
        }

@@ -502,5 +492,28 @@ namespace CountDownList.Controls
            }
        }
#pragma warning restore CS8602 // 解引用可能出现空引用。


        public void BatchUpdate()
        {
            // 禁用布局计算
            this.BeginInit();

            SyncProgress();
            SyncTime();
            SyncTitle();

            // 恢复并触发单次布局
            this.EndInit();
        }









    }
}
+5 −1
Original line number Diff line number Diff line
@@ -134,7 +134,11 @@
                            <GradientStop Color="White" Offset="0.98"/>
                        </LinearGradientBrush>
                    </local:MyScrollViewer.OpacityMask>
                    <VirtualizingStackPanel>
                    <VirtualizingStackPanel
                            VirtualizingPanel.VirtualizationMode="Recycling"
                            VirtualizingPanel.IsVirtualizing="True"
                            VirtualizingPanel.CacheLength="2,2"
                    >
                        <Expander RenderOptions.ClearTypeHint="Enabled" x:Name="DoingE" Background="#00F7F7F7" BorderBrush="{x:Null}" IsExpanded="True" Header="进行中(5)" Margin="4,0,4,0" Foreground="#FFF7F7F7">
                            <VirtualizingStackPanel x:Name="doingList">
                                <!-- 进行中的倒计时项 -->
+1 −1
Original line number Diff line number Diff line
@@ -189,7 +189,7 @@ namespace CountDownList
                EnableBlur();

            DateTime time = DateTime.Now;
            Core = new(doingList, wancheng, count, DoingE, wcE, countE, sv);
            Core = new(doingList, wancheng, count, DoingE, wcE, countE, sv, sv);
            bool initShowed = false;

            foreach (ListLabel item in xml.GetListLabels())