大写来讨论一下循环死机的问题,顶者有分

smking 2008-11-10 04:15:06
一个winform上一个按钮,一个lable1,按钮事件为:
private void button3_Click(object sender, EventArgs e)
{
for (int i = 0; i < 100000;i++ )
{
label1.Text = i.ToString();
}
}

运行并点击按钮,结果:程序无响应,为何?(这里就不要讨论使用计时器什么的,只需要来解释解释为啥就死了呢?)
如果把循环次数设置成1000或者10000次基本没啥问题。(如果效果不明显的话,可以把循环次数改大一点!)
即便是运行10万次,按照现在CPU的速度,也应该很快就执行完毕了啊!
经试验,如果把label1.text = i.ToString()去掉的话,就不会死机了,但仍然执行完了10万次的循环,因此我个人认为这与winform的刷新界面有关,
请各位高人都来讲一讲,这个刷新的过程,以及被刷新的前提,和刷新原理。
...全文
252 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
smking 2008-11-24
  • 打赏
  • 举报
回复
揭帖,顺便总结一下各位高人的发言。

这里面确实涉及到线程的调用,但是由于只有这里没有写其它什么线程在这里,所以我的理解是这里只会有一个主线程即界面线程,而如果加入一个System.Threading.Sleep(xx).那么只是要求这个主线程执行时sleep()一下而已,所以是没有效果的,(我已经试验过。)
也许这里如果再加一个逻辑线程来做这事,并在这个逻辑线程中加入Sleep()的话,应该是可行的。

用for (int i = 0; i < 100000; i++)
{
this.Text = i.ToString();
Application.DoEvents();
}

确实可以搞定,正解!


感谢大家的发言。
ty850818 2008-11-10
  • 打赏
  • 举报
回复
帮顶~
haifeng39 2008-11-10
  • 打赏
  • 举报
回复
mark~
up~
happychou 2008-11-10
  • 打赏
  • 举报
回复
帮顶了。。。。
  • 打赏
  • 举报
回复
mark,友情UP
evjen 2008-11-10
  • 打赏
  • 举报
回复
帮顶
fskjb01 2008-11-10
  • 打赏
  • 举报
回复
关注!!
qinqinhao 2008-11-10
  • 打赏
  • 举报
回复
ding
ft5163541 2008-11-10
  • 打赏
  • 举报
回复
学习,UP
birdlonger 2008-11-10
  • 打赏
  • 举报
回复
因为你每次i.ToString () 的时候会短暂的创建string 类型的东西. 而且这些还暂时释放不掉,,内存很快就豪尽.不死机才怪! 跟线程没什么关系的!
haiyangshao 2008-11-10
  • 打赏
  • 举报
回复
我试了一下,程序并没有死机,只是程序在后台运行的时间比较久而已。
如果把
label1.Text = i.ToString();
语句去掉,程序当然会很快,因为这时候CPU执行的实际命令语句总数不会超过 i 的10倍
但是添加了label1.Text = i.ToString();
语句就不同了,计算机会调用Windows API, 要将很多程序数据压入堆栈,然后返回时再还原。
执行 label1.Text = i.ToString(); 语句时,
Windows还需要调用图形库,计算出字体的形状、大小、点阵,然后在计算并输出到窗口上,这一条语句,CPU中实际执行的语句,至少达到1000句以上
,所以程序比没有这条语句慢上100倍很正常。




aboiljelly 2008-11-10
  • 打赏
  • 举报
回复
每次操作都要装箱的 所以很慢啊 而且耗费资源
dahai99007 2008-11-10
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 dahai99007 的回复:]
引用楼主 smking 的帖子:
一个winform上一个按钮,一个lable1,按钮事件为:
private void button3_Click(object sender, EventArgs e)
{
for (int i = 0; i < 100000;i++ )
{
label1.Text = i.ToString();
}
}

运行并点击按钮,结果:程序无响应,为何?(这里就不要讨论使用计时器什么的,只需要来解释解释为啥就死了呢?)

[/Quote]
有不同意见的,欢迎拍砖!
dahai99007 2008-11-10
  • 打赏
  • 举报
回复
[Quote=引用楼主 smking 的帖子:]
一个winform上一个按钮,一个lable1,按钮事件为:
private void button3_Click(object sender, EventArgs e)
{
for (int i = 0; i < 100000;i++ )
{
label1.Text = i.ToString();
}
}

运行并点击按钮,结果:程序无响应,为何?(这里就不要讨论使用计时器什么的,只需要来解释解释为啥就死了呢?)
如果把循环次数设置成1000或…
[/Quote]
这里边涉及到装箱的问题,装箱过程需要进行大量的计算。
对值类型进行装箱时,必须分配并构造一个全新的对象。
cpu运算的速度非常快,极短的时间构造了那么多对象,而堆上的资源又是有限的,当然会死了(如果加try catch的话可能会出个memoryException,没试!),个人认为和刷新界面没有什么关系。
都说6楼和11楼的能解决问题(System.Threading.Sleep(xx);)我也认为能解决问题,1毫秒对计算机来说时间已经不短了。
yanlongwuhui 2008-11-10
  • 打赏
  • 举报
回复
循环体中加入Application.DoEvents或是System.Threading.Sleep(xxx)

[Quote=引用 ArLi2003 的回复:]
Application.DoEvents 是先中断出让给其它程序去执行(转让消息队列优先权),如果没有消息就返回本程序继续执行下一句

而System.Threading.Thread.Sleep(2000) 是不管当前队列有没有消息等待系统处理都强制当前线程(自己)睡觉一定时间。。
[/Quote]
firhallyj 2008-11-10
  • 打赏
  • 举报
回复
6楼11楼正解 应该可以解决
gengaixue 2008-11-10
  • 打赏
  • 举报
回复
呵呵 学习中…… 顶
真相重于对错 2008-11-10
  • 打赏
  • 举报
回复
反汇编一下label.text 的代码就清楚了
他不是简单的修改label的text属性,它涉及大量的win32的操作
[SRDescription("ControlTextDescr"), Bindable(true), SRCategory("CatAppearance"), Localizable(true), DispId(-517)]
public virtual string Text
{
get
{
if (!this.CacheTextInternal)
{
return this.WindowText;
}
if (this.text != null)
{
return this.text;
}
return "";
}
set
{
if (value == null)
{
value = "";
}
if (value != this.Text)
{
if (this.CacheTextInternal)
{
this.text = value;
}
this.WindowText = value;
this.OnTextChanged(EventArgs.Empty);
if (this.IsMnemonicsListenerAxSourced)
{
for (Control control = this; control != null; control = control.ParentInternal)
{
ActiveXImpl impl = (ActiveXImpl) control.Properties.GetObject(PropActiveXImpl);
if (impl != null)
{
impl.UpdateAccelTable();
return;
}
}
}
}
}
}

其实有个另外一个方法方法

就是调用SetWindowText Api
[DllImport("user32.dll")]
public extern static int SetWindowText(IntPtr handler , string text );
public Form1()
{
InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 100000; i++)
{
SetWindowText(this.label1.Handle, i.ToString());
}

}
冷月孤峰 2008-11-10
  • 打赏
  • 举报
回复
加:System.Threading.Sleep(xx);解决
hangang7403 2008-11-10
  • 打赏
  • 举报
回复
只能用多线程来解决
加载更多回复(9)

110,534

社区成员

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

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

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