WPF 简单的内存优化

WPF的内存问题困扰了很久.

众所周知,如果长时间使用WPF的程序,它的内存占有将会持续增长。甚至持续的点击一个Button,它的内存也会不断的增长。这是我觉得WPF唯一不够尽人意的地方吧。

那么,难道就没有改善WPF内存的方法吗?

在网上搜索了很久,终于找到了一个比较可行的办法。

首先,感谢网友的分享:

http://www.dotnetdev.cn/2010/04/wpf内存释放解决方案/

这个方法的意思是当程序处于闲置状态时(即改程序处于未激活状态),那么我们可以通过kernel32.dll将物理内存与虚拟内存进行交换。即将主内存的资源暂时放到虚拟内存中。这样就减轻了物理内存的负担。

MSDN对这个函数的解释:

使用这个函数来设置应用程序最小和最大的运行空间,只会保留需要的内存。当应用程序被闲置或系统内存太低时,操作系统会自动调用这个机制来设置应用程序的内存。应用程序也可以使用 VirtualLock 来锁住一定范围的内存不被系统释放。

当你加大运行空间给应用程序,你能够得到的物理内存取决于系统,这会造成其他应用程序降低性能或系统总体降低性能,这也可能导致请求物理内存的操作失败,例如:建立 进程,线程,内核池,就必须小心的使用该函数。

实际上,这个函数并不能真正的释放内存,而只是重新分配改程序的内存占用,将暂时不需要的内容放进虚拟内存,当应用程序重新激活时,会将虚拟内存的内容重新加载到内存。所以,我们不宜过度频繁的调用该方法,这样只会使性能变低。

实际使用中,我们只需要当窗口关闭时,或者最小化时调用此方法即可解决内存不能释放的问题,该方法同样适用于Silverlight和Winform。

        [DllImport("kernel32.dll")] public static extern int SetProcessWorkingSetSize(IntPtr proc, int min, int max);
        protected override void OnDeactivated(EventArgs e)
        {
            base.OnDeactivated(e);
            SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
        }

注册事件,定时清楚内存

 DispatcherTimer GCTimer = new DispatcherTimer();
        public MainWindow()
        {
            LogHelper.WriteLog(typeof(MainWindow), "开始 InitializeComponent();");
            InitializeComponent();
            this.GCTimer.Interval = TimeSpan.FromMinutes(1); //垃圾释放定时器 我定为每十分钟释放一次,大家可根据需要修改
            this.GCTimer.Start();
            this.EventsRegistion();    // 注册事件
            LogHelper.WriteLog(typeof(MainWindow), "结束 InitializeComponent();");
        }
        private void add_Item_Click(object sender, RoutedEventArgs e)
        {
            LayoutAnchorable layOutAnc = new LayoutAnchorable() { Title = "新选项卡" + 1 };
            layOutAnc.Content = new TextBox() { Text = "这是第" + 1 + "个新选项卡" };
            layOutPanel.Children.Add(layOutAnc as ILayoutPanelElement);
        }
        public void EventsRegistion()
        {
            this.GCTimer.Tick += new EventHandler(OnGarbageCollection);
        }
        public void EventDeregistration()
        {
            this.GCTimer.Tick -= new EventHandler(OnGarbageCollection);
        }
        void OnGarbageCollection(object sender, EventArgs e)
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
        }

补充:后来发现也可以通过限制程序的使用内存进行优化。但是这需要知晓程序的最大内存占有。

        int maxWorkingSet = 1024000;
        public static void SetWorkingSet(int maxWorkingSet)
        {
            IntPtr min = System.Diagnostics.Process.GetCurrentProcess().MinWorkingSet;
            try
            {
                System.Diagnostics.Process.GetCurrentProcess().MaxWorkingSet = (IntPtr)maxWorkingSet;
            }
            catch ()
            {
                System.Diagnostics.Process.GetCurrentProcess().MaxWorkingSet = min;
            }

        }

 private void Window_Deactivated(object sender, EventArgs e)
        {
            try
            {
                SetWorkingSet(maxWorkingSet);
            }
            catch ()
            {

            }
        }

转载  点击打开链接

猜你喜欢

转载自blog.csdn.net/qq_28368039/article/details/81011012
WPF
今日推荐