线程委托内存泄漏的问题

sdpdww 2015-11-01 01:21:17
第一段代码 ,存在问题,内存一直呈8k增长,进程句柄一直在增长。
delegate void aa(string s);//创建一个代理
private void pri(string t)//这个就是我们的函数,我们把要对控件进行的操作放在这里
{
if (!label1.InvokeRequired)
{
richTextBox1.Text =t;
}
else
{
aa a1 =new aa(pri);
Invoke(a1,new object []{t});
}
}

private void Form1_Load(object sender, System.EventArgse)
{
Thread newthread = new Thread(new ThreadStart(ttread));
newthread.Start();
}
void ttread()
{
while(true)
{
pri("sdfs");
}

}


第二段代码 ,遇到的问题,内存还是一直增长,但是句柄数正常,没有增长。
System.Timers.Timer t = new System.Timers.Timer(2000);

private void Form1_Load(object sender, EventArgs e)
{
t.Elapsed += new System.Timers.ElapsedEventHandler(Timer_TimesUp);
t.AutoReset = false;
}

int ncount = 0;
private void UpdateUI(string str)
{

ncount++;
this.label1.Text = ncount.ToString();
}



public delegate void MyInvoke(string str);
private void Timer_TimesUp(object sender, System.Timers.ElapsedEventArgs e)
{

t.Stop();
MyInvoke mi = new MyInvoke(this.UpdateUI);

this.BeginInvoke(mi, new object[] { "" });
t.Start();

}



两段代码其实都是在一直执行任务,但是这两段代码,其实都是只是在界面上显示简单的信息,但是为何会一直内存和句柄泄漏呢?是c#本身机制的问题?还是说增长到一定程度,c#会自动回收?
如果能修改,应该怎么改呢?
...全文
271 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
veryshy 2017-03-16
  • 打赏
  • 举报
回复
把new移到外面也不行,是invoke导致的内存泄漏,我试过,把委托写道外面,然后只执行invoke,依然不行
veryshy 2017-03-16
  • 打赏
  • 举报
回复
把new移到外面也不行,是invoke导致的内存泄漏,我试过,把委托写道外面,然后只执行invoke,依然不行
winnowc 2015-11-02
  • 打赏
  • 举报
回复
引用 5 楼 sdpdww 的回复:
原来做c++的,现在用csharp做很多不熟悉地地方。我上面德代码,能否帮我改一下。还有你说不存在内存泄露,但是为何一直增长呢?在c++里new了要delete,csharp里没有,所以一看到内存持续增长,就害怕长时间运行会出问题。 麻烦帮我把代码改一下吧,非常感谢。
.net 这托管环境就是让你不用操心delete,GC 帮你管理内存来提高生产力。然而 GC 什么时候进行回收不是你控制的(一般也不应该控制)。从c++过来需要适应下,手动驾驶的车变成自动驾驶了,是不是反而不放心了,觉得总会出事。 你需要的不是让那段代码的内存不增长,而是运行足够长的时间,看看能增长到多少。并不是看到增长就是内存泄漏。带 GC 的环境的内存占用基本都是锯齿状的,慢慢增长,GC 后回落,再慢慢增长,GC后再回落,和 c++ 程序不是一个模式的。
事理 2015-11-01
  • 打赏
  • 举报
回复
用这个通用的吧,测试过没有出现这种问题。 http://www.cnblogs.com/slyzly/articles/2121436.html
sdpdww 2015-11-01
  • 打赏
  • 举报
回复
引用 4楼winnowc 的回复:
这两种都不存在内存泄漏,第二种句柄没变化是因为用了 BeginInvoke 而不是 Invoke,Control上的 Invoke 是相当低效的实现,内部使用了 ManualResetEvent,它就是增长的那个句柄。 重复的创建 Delegate 和 new object[] 是内存增长的主因,不过一般这都不是问题,而且并不容易检查(比如如果参数需要int 转换object传递,这种装箱也要占用内存)。不嫌麻烦可以都放外面创建一次。如果你用 Resharper,它有个插件叫 Heap Allocations Viewer,可以方便检查这些内存分配。 因为GC机制,想确定有没有内存泄漏需要完全GC才能判断。你可以用一个按钮或者定时调用下面的代码再看结果(不过GC本身也要占用内存,如果第一次GC前内存占用并不大,GC之后反而可能变大哦):

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
原来做c++的,现在用csharp做很多不熟悉地地方。我上面德代码,能否帮我改一下。还有你说不存在内存泄露,但是为何一直增长呢?在c++里new了要delete,csharp里没有,所以一看到内存持续增长,就害怕长时间运行会出问题。 麻烦帮我把代码改一下吧,非常感谢。
winnowc 2015-11-01
  • 打赏
  • 举报
回复
这两种都不存在内存泄漏,第二种句柄没变化是因为用了 BeginInvoke 而不是 Invoke,Control上的 Invoke 是相当低效的实现,内部使用了 ManualResetEvent,它就是增长的那个句柄。 重复的创建 Delegate 和 new object[] 是内存增长的主因,不过一般这都不是问题,而且并不容易检查(比如如果参数需要int 转换object传递,这种装箱也要占用内存)。不嫌麻烦可以都放外面创建一次。如果你用 Resharper,它有个插件叫 Heap Allocations Viewer,可以方便检查这些内存分配。 因为GC机制,想确定有没有内存泄漏需要完全GC才能判断。你可以用一个按钮或者定时调用下面的代码再看结果(不过GC本身也要占用内存,如果第一次GC前内存占用并不大,GC之后反而可能变大哦):

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
sdpdww 2015-11-01
  • 打赏
  • 举报
回复
引用 2楼ajianchina 的回复:
第一段 aa a1 =new aa(pri); 第二段 MyInvoke mi = new MyInvoke(this.UpdateUI); 移到外面,不要一直new出新对象 还有,你第一段代码运行的时候ui会感觉到卡吗?
卡不卡倒是能解决,你的意思是因为反复new的原因?
ajianchina 2015-11-01
  • 打赏
  • 举报
回复
第一段 aa a1 =new aa(pri); 第二段 MyInvoke mi = new MyInvoke(this.UpdateUI); 移到外面,不要一直new出新对象 还有,你第一段代码运行的时候ui会感觉到卡吗?
sdpdww 2015-11-01
  • 打赏
  • 举报
回复
自己顶一下,希望高手能看到。
线程 单例模式下的线程安全http://blog.sina.com.cn/s/blog_75247c770100yxpb.html map集合 集合数据结构及方法的使用 多线程 线程进程 线程状态 线程状态的改变 sql :临时表、游标、存贮过程、触发机制http://www.cnblogs.com/SkySoot/archive/2012/04/09/2439190.html jvm工作原理 JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。 1说说JVM原理?内存泄露与溢出区别,何时产生内存泄露? 编译源代码为本地机器码执行。 内存泄露是一部分内存无法回收。溢出是说内存不够用了。泄露可能在将来会导致溢出 当对象在程序中不会被使用,但却有其他对象持有该对象时会发生溢出。比如出现持有的环的情况。 java并发面试题 .内存存储锁控制 http://blog.csdn.net/geolo/article/details/8670900 4.请说明下java的内存模型及其工作流程。 答:Java把内存划分成两种:一种是栈内存,一种是堆内存。 栈内存:存放对象:函数中基本类型的变量和对象的引用变量、静态类方法 ;特点:栈有一个很重要的特殊性,就是存在栈中的数据可以共享。 堆内存:存放对象:用来存放由new创建的对象和数组;特点:在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。 java 内存模型 ( java memory model ):根据Java Language Specification中的说明, jvm系统中存在一个主内存(Main Memory或Java Heap Memory),Java中所有对象成员变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些对象成员变量的拷贝,线程对所有对象成员变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。 (1) 获取对象监视器的锁(lock) (2) 清空工作内存数据, 从主存复制对象成员变量到当前工作内存, 即同步数据 (read and load) (3) 执行代码,改变共享变量值 (use and assign) (4) 将工作内存数据刷回主存 (store and write) (5) 释放对象监视器的锁 (unlock) spring框架原理 10. spring工作机制及为什么要用? 1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作。 2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller. 3.DispatcherServlet请求提交到目标Controller 4.Controller进行业务逻辑处理后,会返回一个ModelAndView 5.Dispathcher查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象 6.视图对象负责渲染返回给客户端。
java核心面试技术点 线程 单例模式下的线程安全http://blog.sina.com.cn/s/blog_75247c770100yxpb.html map集合 集合数据结构及方法的使用 多线程 线程进程 线程状态 线程状态的改变 sql :临时表、游标、存贮过程、触发机制http://www.cnblogs.com/SkySoot/archive/2012/04/09/2439190.html jvm工作原理 JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。 1说说JVM原理?内存泄露与溢出区别,何时产生内存泄露? 编译源代码为本地机器码执行。 内存泄露是一部分内存无法回收。溢出是说内存不够用了。泄露可能在将来会导致溢出 当对象在程序中不会被使用,但却有其他对象持有该对象时会发生溢出。比如出现持有的环的情况。 java并发面试题 .内存存储锁控制 http://blog.csdn.net/geolo/article/details/8670900 4.请说明下java的内存模型及其工作流程。 答:Java把内存划分成两种:一种是栈内存,一种是堆内存。 栈内存:存放对象:函数中基本类型的变量和对象的引用变量、静态类方法 ;特点:栈有一个很重要的特殊性,就是存在栈中的数据可以共享。 堆内存:存放对象:用来存放由new创建的对象和数组;特点:在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。 java 内存模型 ( java memory model ):根据Java Language Specification中的说明, jvm系统中存在一个主内存(Main Memory或Java Heap Memory),Java中所有对象成员变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些对象成员变量的拷贝,线程对所有对象成员变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。 (1) 获取对象监视器的锁(lock) (2) 清空工作内存数据, 从主存复制对象成员变量到当前工作内存, 即同步数据 (read and load) (3) 执行代码,改变共享变量值 (use and assign) (4) 将工作内存数据刷回主存 (store and write) (5) 释放对象监视器的锁 (unlock) spring框架原理 10. spring工作机制及为什么要用? 1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作。 2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller. 3.DispatcherServlet请求提交到目标Controller 4.Controller进行业务逻辑处理后,会返回一个ModelAndView 5.Dispathcher查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象 6.视图对象负责渲染返回给客户端。

110,533

社区成员

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

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

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