DynamicMethod 内存释放问题

nikychen 2010-03-12 01:44:04
执行完后 通过.net 内存监视器 发现 lstData 内所有的对象都没有释放。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection.Emit;
using System.Reflection;
using System.Runtime.InteropServices;

namespace TestEmit {
class Program {
static void Main(string[] args) {
Test t = new Test();
t.t();
GC.Collect();
Console.ReadLine();
}
}
public class Test {
public void t() {
var r = SetPropertyValue(typeof(TestClass), "Name");
List<object> lstData = new List<object>();
for (int i = 0; i < 1000000; i++) {
TestClass t = new TestClass();
r.Invoke(null, new object[]{t,"AAA" + i });
lstData.Add(t);
}

}
//public delegate void SetPropertyDelegate(object obj, object m_Value);
public static DynamicMethod SetPropertyValue(Type oType, string propertyName) {
PropertyInfo pi = oType.GetProperty(propertyName);

if (pi != null) {
string methodName = pi.Name;

DynamicMethod dm = new DynamicMethod("XXXXX_" + methodName,typeof(void),
new Type[] { typeof(object), typeof(object) }, pi.Module, true);
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);

il.Emit(OpCodes.Ldarg_1);

il.EmitCall(OpCodes.Callvirt, pi.GetSetMethod(true), null);

if (pi.PropertyType.IsValueType) {
il.Emit(OpCodes.Unbox_Any, pi.PropertyType);
}
il.Emit(OpCodes.Ret);
return dm;
//return (SetPropertyDelegate)dm.CreateDelegate(typeof(SetPropertyDelegate));
}
else {
throw new NullReferenceException("exception");
}
}
}
public class TestClass {
public string Name { get; set; }
public string Code { get; set; }
public string Address { get; set; }
}



}
...全文
194 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
li45214521 2010-03-13
  • 打赏
  • 举报
回复
windbg这个好像不能监视托管堆的释放吧
天乐 2010-03-13
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 nikychen 的回复:]
谢谢你的回复。
但我想把 DynamicMethod(无法系列化) 传出来,这样调用性能会快一些,如果每调用一个属性都需要创建一个新的DynamicMethod倒不如直接用反射来的直接一点。
[/Quote]

确实不如改用反射,代码可读性也强一点
nikychen 2010-03-13
  • 打赏
  • 举报
回复
我测试了,结果是一样的
天乐 2010-03-12
  • 打赏
  • 举报
回复
试试release模式下结果是否和debug模式下相同
nikychen 2010-03-12
  • 打赏
  • 举报
回复
lzsh0622:
不可能的~~~你用windbg 看看 :)
lzsh0622 2010-03-12
  • 打赏
  • 举报
回复
我测试结果,已经释放了。去掉GC.Collect(); 内存多占用60M

把回收提到上一工作域,效果相同.
nikychen 2010-03-12
  • 打赏
  • 举报
回复
谢谢你的回复。
但我想把 DynamicMethod(无法系列化) 传出来,这样调用性能会快一些,如果每调用一个属性都需要创建一个新的DynamicMethod倒不如直接用反射来的直接一点。

xingyuebuyu 2010-03-12
  • 打赏
  • 举报
回复
可以创建一个AppDomain,将Assembly放到新建的AppDomain中运行,运行完后再卸载AppDomain

http://www.cnblogs.com/cyan/archive/2009/05/09/1453278.html
nikychen 2010-03-12
  • 打赏
  • 举报
回复
GC.Collect();添加在这里只是方便内存监视而已,可以去掉。
lstData 中所有对象没有被释放,应该还存在被引用。
初步分析下来应该是DynamicMethod 创建的 assembly 没有被释放。
但不知道怎么解决?
xingyuebuyu 2010-03-12
  • 打赏
  • 举报
回复
GC.Collect();
GC.WaitForPendingFinalizers();

两个一起调用,只调用GC.Collect();垃圾收集器的动作是没那么快的,你需要等待它完成该线程上的清理工作。
nikychen 2010-03-12
  • 打赏
  • 举报
回复
难道是dotnet 的bug?
nikychen 2010-03-12
  • 打赏
  • 举报
回复
问题是 gc 没有处理
特别安静 2010-03-12
  • 打赏
  • 举报
回复
。net不是有gc可以自己处理的吗?

110,567

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧