现象记录

  • 前段时间同事发现我们的软件在加载指定的插件界面后,关闭后插件的界面资源不能释放, 资源管理器中不管内存,还是GDI对象等相关资源都不会下降。

问题代码

  • 问题的代码大概如下。
public void LoadPluginUI(string pluginID)
{
this.Control.Clear();
Control ctl = GetPluginUI(pluginID);// ctl是我们插件的用户控件
this.Control.Add(ctl);
}

原因与解决方案

原因分析

解决问题的思路主要还是上windbg用sos的gcroot查引用根(这里由于还有终结者队列的根,实际会让人很迷惑)。可以发现在GC句柄表里有定时器导致资源无法释放。

在.Net下主要有4类地方会持有引用根,从而使得对象在标记阶段被标记,导致GC不会回收该对象。

参考《.Net内存管理宝典》 第八章,垃圾回收-标记阶段

  • 线程栈
  • GC内部根(跨代引用,类静态变量等)
  • 终结器队列
  • GC句柄表

这里定时器的引用根在GC句柄表,通过sos可以查到定时器的周期为300ms。由于我们的代码里没有这样的定时器,最终怀疑到DevExpress的代码中,通过检查SOS的引用链 最终发现我们使用的DataLayoutControl有问题。

DevExpress的相关源代码如下:

LayoutControl.cs

private void Initialize() {
SetStyle(ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor, true);
implementorCore.InitializeComponents();
} ILayoutControlImplementer.cs
public virtual void InitializeComponents() {
if(AllowCreateRootElement) InitializeRootGroupCore();
InitializeCollections();
InitializeTimerHandler();
InitializeScrollerCore(as_I);
InitializeFakeFocusContainerCore(as_I);
} public virtual void InitializeTimerHandler()
{
if(AllowTimer) {
this.internalTimerCore = new Timer();
InternalTimer.Interval = 300;
// DevExpress的LayoutControl内部使用这个定时器计算布局等
InternalTimer.Tick += OnTimedEvent;
InternalTimer.Enabled = true;
}
} protected virtual bool AllowTimer {
get { return true; }
} internal void OnTimedEvent(object sender, EventArgs e) {
if(as_I.IsUpdateLocked) return;
as_I.ActiveHandler.OnTimer();
} public virtual void OnTimer() {
AutoScrollByMoving();
InvalidateHotTrackItemIfNeed();
}
  • DataLayoutControl继承自LayoutControl,自然就有了该问题。

教训

不用的控件需要主动Dispose,不能Remove就不管了。

Winform的Dispose会自动处理子控件,所以不论我们的用户控件内部如何嵌套。直接对最外层处理Dispose就可以了。

Winform的相关代码如下:

protected override void Dispose(bool disposing)
{
// 对内部维护的资源进行释放
ControlCollection controlCollection = (ControlCollection)Properties.GetObject(PropControlsCollection);
if (controlCollection != null)
{
for (int i = 0; i < controlCollection.Count; i++)
{
Control control = controlCollection[i];
control.parent = null;
control.Dispose();
}
Properties.SetObject(PropControlsCollection, null);
}

解决方案代码

public void LoadPluginUI(string pluginID)
{
this.Control[0].Dispose();
Control ctl = GetPluginUI(pluginID);// ctl是我们插件的用户控件
this.Control.Add(ctl);
}

DevExpress 的LayoutControl控件导致资源无法释放的问题处理的更多相关文章

  1. DevExpress Winform 常用控件

    Ø  前言 DevExpress 控件的功能比较强大,是全球知名控件开发公司,对于开发 B/S 或 C/S 都非常出色,可以实现很炫且功能强大的效果. DevExpress Winform 常用控件是 ...

  2. DevExpress Winform 通用控件打印方法(允许可自定义边距) z

    DevExpress Winform 通用控件打印方法,包括gridcontrol,treelist,pivotGridControl,ChartControl,LayoutControl...(所有 ...

  3. DevExpress之GridControl控件小知识

    DevExpress之GridControl控件小知识 一.当代码中的DataTable中有建数据关系时,DevExpress 的 GridControl 会自动增加一个子视图 .列名也就是子表的字段 ...

  4. WPF Popup 控件导致被遮挡内容不刷新的原因

    WPF Popup 控件导致被遮挡内容不刷新的原因 周银辉 今天在写一个WPF控件时用到了Popup控件,很郁闷的情况是:当popup关闭时,原来被popup挡住的界面部分不刷新,非要手动刷新一下(比 ...

  5. (转)WPF控件开源资源

    (转)WPF控件开源资源 Textbox Drag/Drop in WPFhttp://www.codeproject.com/Articles/42696/Textbox-Drag-Drop-in- ...

  6. DevExpress的GridControl控件更新數據問題解決辦法

    開發WPF程序時,使用Devexpress的GridControl控件用ItemSource綁定數據,在頁面進行編輯時,當屬性繼承INotifyPropertyChanged接口時會同步更新後臺數據. ...

  7. DevExpress的Web控件汉化方法

    原文:DevExpress的Web控件汉化方法 项目中用到devexpress的web控件,机器没有安装devexpress控件,直接在项目中引用的dev的dll,项目运行时发现都是英文界面,所以解决 ...

  8. 使用DevExpress.XtraTabbedMdi.XtraTabbedMdiManager控件来加载MDI窗体

    使用DevExpress.XtraTabbedMdi.XtraTabbedMdiManager控件来加载MDI窗体     [csharp] view plaincopyprint? <SPAN ...

  9. 玩转控件:重绘DEVEXPRESS中DateEdit控件 —— 让DateEdit支持只选择年月 (提供源码下载)

      前言 上一篇博文<玩转控件:重绘ComboBox —— 让ComboBox多列显示>中,根据大家的回馈,ComboBox已经支持筛选了,更新见博文最后最后最后面.   奇葩 这两天遇到 ...

  10. WPF控件开源资源

    (转)WPF控件开源资源 Textbox Drag/Drop in WPFhttp://www.codeproject.com/Articles/42696/Textbox-Drag-Drop-in- ...

随机推荐

  1. hwj是猪

    黄伟佳不爱我了吧唧吧唧

  2. 17.MongoDB系列之了解应用程序动态

    1. 查看当前操作 mongos> db.currentOp() { "inprog" : [ { "shard" : "study" ...

  3. Doris开发手记4:倍速性能提升,向量化导入的性能调优实践

    最近居家中,对自己之前做的一些工作进行总结.正好有Doris社区的小伙伴吐槽向量化的导入性能表现并不是很理想,就借这个机会对之前开发的向量化导入的工作进行了性能调优,取得了不错的优化效果.借用本篇手记 ...

  4. k8s之pod连接被拒排查

    k8s之pod连接被拒排查 pod链接被拒 查看pod的时候发现pod的状态为crashloopbackoff 然后看看日志发现报错如下 kubectl -n kf10 logs easydata-r ...

  5. vulnhub靶场之ICA: 1

    准备: 攻击机:虚拟机kali.本机win10. 靶机:ICA: 1,网段地址我这里设置的桥接,所以与本机电脑在同一网段,下载地址:https://download.vulnhub.com/ica/i ...

  6. vulnhub靶场之Beelzebub

    准备: 攻击机:虚拟机kali.本机win10. 靶机:Beelzebub: 1,网段地址我这里设置的桥接,所以与本机电脑在同一网段,下载地址:https://download.vulnhub.com ...

  7. 2022-11-09 Acwing每日一题

    本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的.同时也希望 ...

  8. 2022春每日一题:Day 23

    题目:Piotr's Ants 蚂蚁转头走,其实可以看做他们交换灵魂后接着往前走,同样发现,既然他们的速度相同,那么在数轴上相对位置不会改变(碰面会改变方向),那就好办了. 先把初始状态排序,id都记 ...

  9. java 分布式游戏服务器框架,集群游戏服务器框架,游戏服务器网关框架 ioGame 网络游戏服务器框架

    ioGame 国内首个基于蚂蚁金服 SOFABolt 的 java 网络游戏服务器框架:无锁异步化.事件驱动的架构设计 通过 ioGame 可以很容易的搭建出一个集群无中心节点.有状态多进程的分步式游 ...

  10. HDLBits答案——Verilog Language

    Verilog Language 1 Basics 1.1 Wire module top_module( input in, output out ); assign out = in; endmo ...