DevExpress 的LayoutControl控件导致资源无法释放的问题处理
现象记录
- 前段时间同事发现我们的软件在加载指定的插件界面后,关闭后插件的界面资源不能释放, 资源管理器中不管内存,还是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控件导致资源无法释放的问题处理的更多相关文章
- DevExpress Winform 常用控件
Ø 前言 DevExpress 控件的功能比较强大,是全球知名控件开发公司,对于开发 B/S 或 C/S 都非常出色,可以实现很炫且功能强大的效果. DevExpress Winform 常用控件是 ...
- DevExpress Winform 通用控件打印方法(允许可自定义边距) z
DevExpress Winform 通用控件打印方法,包括gridcontrol,treelist,pivotGridControl,ChartControl,LayoutControl...(所有 ...
- DevExpress之GridControl控件小知识
DevExpress之GridControl控件小知识 一.当代码中的DataTable中有建数据关系时,DevExpress 的 GridControl 会自动增加一个子视图 .列名也就是子表的字段 ...
- WPF Popup 控件导致被遮挡内容不刷新的原因
WPF Popup 控件导致被遮挡内容不刷新的原因 周银辉 今天在写一个WPF控件时用到了Popup控件,很郁闷的情况是:当popup关闭时,原来被popup挡住的界面部分不刷新,非要手动刷新一下(比 ...
- (转)WPF控件开源资源
(转)WPF控件开源资源 Textbox Drag/Drop in WPFhttp://www.codeproject.com/Articles/42696/Textbox-Drag-Drop-in- ...
- DevExpress的GridControl控件更新數據問題解決辦法
開發WPF程序時,使用Devexpress的GridControl控件用ItemSource綁定數據,在頁面進行編輯時,當屬性繼承INotifyPropertyChanged接口時會同步更新後臺數據. ...
- DevExpress的Web控件汉化方法
原文:DevExpress的Web控件汉化方法 项目中用到devexpress的web控件,机器没有安装devexpress控件,直接在项目中引用的dev的dll,项目运行时发现都是英文界面,所以解决 ...
- 使用DevExpress.XtraTabbedMdi.XtraTabbedMdiManager控件来加载MDI窗体
使用DevExpress.XtraTabbedMdi.XtraTabbedMdiManager控件来加载MDI窗体 [csharp] view plaincopyprint? <SPAN ...
- 玩转控件:重绘DEVEXPRESS中DateEdit控件 —— 让DateEdit支持只选择年月 (提供源码下载)
前言 上一篇博文<玩转控件:重绘ComboBox —— 让ComboBox多列显示>中,根据大家的回馈,ComboBox已经支持筛选了,更新见博文最后最后最后面. 奇葩 这两天遇到 ...
- WPF控件开源资源
(转)WPF控件开源资源 Textbox Drag/Drop in WPFhttp://www.codeproject.com/Articles/42696/Textbox-Drag-Drop-in- ...
随机推荐
- hwj是猪
黄伟佳不爱我了吧唧吧唧
- 17.MongoDB系列之了解应用程序动态
1. 查看当前操作 mongos> db.currentOp() { "inprog" : [ { "shard" : "study" ...
- Doris开发手记4:倍速性能提升,向量化导入的性能调优实践
最近居家中,对自己之前做的一些工作进行总结.正好有Doris社区的小伙伴吐槽向量化的导入性能表现并不是很理想,就借这个机会对之前开发的向量化导入的工作进行了性能调优,取得了不错的优化效果.借用本篇手记 ...
- k8s之pod连接被拒排查
k8s之pod连接被拒排查 pod链接被拒 查看pod的时候发现pod的状态为crashloopbackoff 然后看看日志发现报错如下 kubectl -n kf10 logs easydata-r ...
- vulnhub靶场之ICA: 1
准备: 攻击机:虚拟机kali.本机win10. 靶机:ICA: 1,网段地址我这里设置的桥接,所以与本机电脑在同一网段,下载地址:https://download.vulnhub.com/ica/i ...
- vulnhub靶场之Beelzebub
准备: 攻击机:虚拟机kali.本机win10. 靶机:Beelzebub: 1,网段地址我这里设置的桥接,所以与本机电脑在同一网段,下载地址:https://download.vulnhub.com ...
- 2022-11-09 Acwing每日一题
本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的.同时也希望 ...
- 2022春每日一题:Day 23
题目:Piotr's Ants 蚂蚁转头走,其实可以看做他们交换灵魂后接着往前走,同样发现,既然他们的速度相同,那么在数轴上相对位置不会改变(碰面会改变方向),那就好办了. 先把初始状态排序,id都记 ...
- java 分布式游戏服务器框架,集群游戏服务器框架,游戏服务器网关框架 ioGame 网络游戏服务器框架
ioGame 国内首个基于蚂蚁金服 SOFABolt 的 java 网络游戏服务器框架:无锁异步化.事件驱动的架构设计 通过 ioGame 可以很容易的搭建出一个集群无中心节点.有状态多进程的分步式游 ...
- HDLBits答案——Verilog Language
Verilog Language 1 Basics 1.1 Wire module top_module( input in, output out ); assign out = in; endmo ...