问题描述
在一个多线程程序中调用richTextBox老是在运行一段时间后报错代码如下,richText在2000行左右的时候就报错未处理的“System.StackOverflowException”类型的异常出现在System.Windows.Forms.dll中。publicvoidLogAppendLine(System.Windows.Forms.RichTextBoxrichTextBoxRemote,Colorcolor,stringtext){if(richTextBoxRemote!=null&&richTextBoxRemote.Parent!=null&&richTextBoxRemote.Parent.IsHandleCreated&&richTextBoxRemote.IsHandleCreated&&!richTextBoxRemote.IsDisposed){try{richTextBoxRemote.InvokeIfNeeded((str)=>{if(richTextBoxRemote.Text.Length>(richTextBoxRemote.MaxLength-100000)){richTextBoxRemote.Clear();}StringBuilderstrb=newStringBuilder(richTextBoxRemote.Text);//strb.Append("");strb.AppendLine(text);//strb.Append("rn");strings=strb.ToString();//这里出错richTextBoxRemote.Text=s;richTextBoxRemote.SelectionColor=color;richTextBoxRemote.Refresh();//richTextBoxRemote.Focus();//获取焦点richTextBoxRemote.Select(richTextBoxRemote.TextLength,0);//光标定位到文本最后richTextBoxRemote.ScrollToCaret();//滚动到光标处Application.DoEvents();},text);}catch(Exceptionex){//throw;}}}
解决方案
解决方案二:
Application.DoEvents();无意义去掉再测试下看看
解决方案三:
不要老去操作滚动条,这样是会报错的你可以把新内容追加到字符串的前面,倒序显示
解决方案四:
引用1楼mervyn807的回复:
Application.DoEvents();无意义去掉再测试下看看
去掉后会假死引用2楼Z65443344的回复:
不要老去操作滚动条,这样是会报错的你可以把新内容追加到字符串的前面,倒序显示
还是会抛出错误if(richTextBoxRemote.Text.Length>(richTextBoxRemote.MaxLength-100000)){到这里就出现了
解决方案五:
再跑一次也出错了
解决方案六:
到底抛什么错误,放出来看看
解决方案七:
引用5楼Z65443344的回复:
到底抛什么错误,放出来看看
未处理的“System.StackOverflowException”类型的异常出现在System.Windows.Forms.dll中。
解决方案八:
如果Application.DoEvents();去掉后会假死,说明你根本没在线程里执行这个代码,阻塞主线程了
解决方案九:
字面上翻译过来是堆栈溢出错误。应该是出现了无限循环或者无限递归
解决方案十:
引用8楼liuhuibing12的回复:
字面上翻译过来是堆栈溢出错误。应该是出现了无限循环或者无限递归
我想了很久,也许和我的业务有关我在多线程中非常频繁的调用这个方法,但是这个方法执行没有调用的快,然后栈中不停的积压这个方法,导致栈空间被使用完了我要怎么改变这个业务才能避免这种错误呢?
解决方案十一:
你想了这么久,都是异想天开。1、先了解下Application.DoEvents交出CPU控制权,让系统可以处理队列中的所有Windows消息,比如在大运算量循环内,加Application.DoEvents可以防止界面停止响应,因为winform的消息循环是一个线程来处理,那么假如你的某个操作比较耗时,那么消息处理得等你这个耗时操作做完了才能继续,而Application.DoEvents方法就是允许你在耗时操作的内部调用它,而去处理消息队列中的消息。像鼠标移动鼠标点击都是windows消息,如果耗时操作一直进行,那么界面就像死锁一样。(耗时操作用的比较多)
2、函数调用,是函数地址入栈,你可以拿你的机器测试下一个函数地址的字节大小。你的调用竟然能把栈耗尽,这个听起来有点滑稽。之所以抛错,估计是你频繁的移动滚轮,造成richtextbox每次重绘,导致堆栈溢出。
解决方案十二:
引用10楼lovelj2012的回复:
你想了这么久,都是异想天开。1、先了解下Application.DoEvents交出CPU控制权,让系统可以处理队列中的所有Windows消息,比如在大运算量循环内,加Application.DoEvents可以防止界面停止响应,因为winform的消息循环是一个线程来处理,那么假如你的某个操作比较耗时,那么消息处理得等你这个耗时操作做完了才能继续,而Application.DoEvents方法就是允许你在耗时操作的内部调用它,而去处理消息队列中的消息。像鼠标移动鼠标点击都是windows消息,如果耗时操作一直进行,那么界面就像死锁一样。(耗时操作用的比较多)2、函数调用,是函数地址入栈,你可以拿你的机器测试下一个函数地址的字节大小。你的调用竟然能把栈耗尽,这个听起来有点滑稽。之所以抛错,估计是你频繁的移动滚轮,造成richtextbox每次重绘,导致堆栈溢出。
估计你没有看我修改后的代码修改后的代码已经去掉了滚动功能我开了1000个线程调用这个函数不用Application.DoEvents肯定会卡死
解决方案十三:
开了1000个线程调用这个函数-----------天雷滚滚!~
解决方案十四:
引用12楼Z65443344的回复:
开了1000个线程调用这个函数-----------天雷滚滚!~
这个是服务端的一段代码,有1000个线程调用是很正常的事
解决方案十五:
引用13楼ayun00的回复:
Quote: 引用12楼Z65443344的回复:
开了1000个线程调用这个函数-----------天雷滚滚!~这个是服务端的一段代码,有1000个线程调用是很正常的事
使用线程池来管理你的线程
其他方案:
引用13楼ayun00的回复:
Quote: 引用12楼Z65443344的回复:
开了1000个线程调用这个函数-----------天雷滚滚!~这个是服务端的一段代码,有1000个线程调用是很正常的事
既然是服务端的代码,为什么要更新到richtextbox里去,谁会看?把结果先保存到list,有人看的时候再用控件显示,没必要实时显示,也不要乱用委托.
其他方案:
引用15楼Z65443344的回复:
Quote: 引用13楼ayun00的回复:
Quote: 引用12楼Z65443344的回复:
开了1000个线程调用这个函数-----------天雷滚滚!~这个是服务端的一段代码,有1000个线程调用是很正常的事
既然是服务端的代码,为什么要更新到richtextbox里去,谁会看?把结果先保存到list,有人看的时候再用控件显示,没必要实时显示,也不要乱用委托.
有时候服务器端程序,也是需要展现信息的。比如前置机,虽然一般没人盯着,但是展示实时请求、应答,还是有意义的。
其他方案:
怎么解决这个问题呢,现在窗口一打开几分钟就溢出了
其他方案:
引用17楼ayun00的回复:
怎么解决这个问题呢,现在窗口一打开几分钟就溢出了
推荐你使用log4net把内容显示在RichTextBox控件
其他方案:
Application.DoEvents执行事件一般WinForm拖动控件或设置消息循环,出现这个堆栈溢出你用这个命令基本是可以解决的。当然不排除你程序有死循环无限递归造成的溢出
其他方案:
引用18楼lovelj2012的回复:
Quote: 引用17楼ayun00的回复:
怎么解决这个问题呢,现在窗口一打开几分钟就溢出了推荐你使用log4net把内容显示在RichTextBox控件
还没有研究过log4net引用19楼Windowsvipcuvs的回复:
Application.DoEvents执行事件一般WinForm拖动控件或设置消息循环,出现这个堆栈溢出你用这个命令基本是可以解决的。当然不排除你程序有死循环无限递归造成的溢出
问题是现在没有解决啊
其他方案:
引用9楼ayun00的回复:
Quote: 引用8楼liuhuibing12的回复:
字面上翻译过来是堆栈溢出错误。应该是出现了无限循环或者无限递归我想了很久,也许和我的业务有关我在多线程中非常频繁的调用这个方法,但是这个方法执行没有调用的快,然后栈中不停的积压这个方法,导致栈空间被使用完了我要怎么改变这个业务才能避免这种错误呢?
对于这种情况我通常是ReactiveExtension去限流,例如典型的每隔1s响应一次,或者采用Throttle,本质上都是为了减少不必要的事件执行。
其他方案:
引用21楼lincolnandlinda的回复:
Quote: 引用9楼ayun00的回复:
Quote: 引用8楼liuhuibing12的回复:
字面上翻译过来是堆栈溢出错误。应该是出现了无限循环或者无限递归我想了很久,也许和我的业务有关我在多线程中非常频繁的调用这个方法,但是这个方法执行没有调用的快,然后栈中不停的积压这个方法,导致栈空间被使用完了我要怎么改变这个业务才能避免这种错误呢?
对于这种情况我通常是ReactiveExtension去限流,例如典型的每隔1s响应一次,或者采用Throttle,本质上都是为了减少不必要的事件执行。
能给个demo吗?
其他方案:
引用21楼lincolnandlinda的回复:
Quote: 引用9楼ayun00的回复:
Quote: 引用8楼liuhuibing12的回复:
字面上翻译过来是堆栈溢出错误。应该是出现了无限循环或者无限递归我想了很久,也许和我的业务有关我在多线程中非常频繁的调用这个方法,但是这个方法执行没有调用的快,然后栈中不停的积压这个方法,导致栈空间被使用完了我要怎么改变这个业务才能避免这种错误呢?
对于这种情况我通常是ReactiveExtension去限流,例如典型的每隔1s响应一次,或者采用Throttle,本质上都是为了减少不必要的事件执行。
百度了下,只看到对textbox的TextChanged的范例,像我这种没有控件,自定义事件的怎么处理
其他方案:
没人玩过这个吗?
其他方案:
先写日志文件里,需要看的时候从文件里读出来看或者后台用个list<string>作为缓存,每秒或者每5秒刷新一次,内容显示到控件过期数据丢弃,或者先写文件再丢弃,否则运行时间一长,内存就爆了不要所有数据都放控件里,即使控件本身没有限制,它毕竟是占内存的,早晚会有内存不足的时候
其他方案:
引用25楼Z65443344的回复:
先写日志文件里,需要看的时候从文件里读出来看或者后台用个list<string>作为缓存,每秒或者每5秒刷新一次,内容显示到控件过期数据丢弃,或者先写文件再丢弃,否则运行时间一长,内存就爆了不要所有数据都放控件里,即使控件本身没有限制,它毕竟是占内存的,早晚会有内存不足的时候
恩我是看到上面兄弟说的ReactiveExtension,有点意思,想弄一下,如果实在没有办法就只有开一个线程去缓存显示了
其他方案:
尝试一下线程池的管理,用好线程池你的这个问题也许就解决了
其他方案:
引用27楼piaopiao_lucky的回复:
尝试一下线程池的管理,用好线程池你的这个问题也许就解决了
没明白你的意思