为什么使用String.Format()设置标签文本在使用某些Int32变量时比使用其他Int32变量快20倍?
c#
无意中发现了一个很奇怪的问题,做了一些测试。我是否发现了一些隐藏的框架错误?
(注意:我使用 Visual Studio 2010,我的目标是 .Net Framework 3.5 Client Profile,但我不明白这可能是什么原因)。
我有一个Windows Forms 项目,带有启动 Timer 组件的表单、标签和按钮(添加到 Visual Studio 设计器中的表单)。
点击一个按钮启动计时器,然后它在 500 毫秒后滴答并停止自己,在运行一些代码之后,这些代码也基于一些 int 变量设置了标签的文本。
private void buttonTest_Click(object sender, EventArgs e)
{
if (!timer1.Enabled)
{
timer1.Start();
}
}
我真的很困惑,为什么以下两个代码的运行速度几乎不一样(以及为什么差异如此巨大)。
到底是怎么回事?请帮我找出原因。
代码 1显示消息,平均显示:“ 00:00:00.050 ”。所以每次我点击一个按钮来重新启动表单的计时器大约需要50 毫秒。
private void timer1_Tick(object sender, EventArgs e)
{
DateTime dt = DateTime.Now;
for (int i = 0; i < 10000; i++)
{
labelTest.Text = String.Format("Text {0}", DateTime.Now.Millisecond);
}
timer1.Stop();
MessageBox.Show((DateTime.Now - dt).ToString());
}
代码 2显示消息,平均显示:“ 00:00:00.900 ”。因此,每次我点击重新启动表单计时器的按钮时,大约需要900 毫秒。
private void timer1_Tick(object sender, EventArgs e)
{
DateTime dt = DateTime.Now;
for (int i = 0; i < 10000; i++)
{
labelTest.Text = String.Format("Text {0}", i);
}
timer1.Stop();
MessageBox.Show((DateTime.Now - dt).ToString());
}
我在这两种情况下都提供 String.Format Int32 值,实际上我希望第一个代码比第二个代码运行稍慢,因为访问 DataTime 的属性......
但是第一个代码运行了 50 毫秒,第二个代码运行了 900 毫秒。
此外,我尝试对timer1.Stop();和 MessageBox 代码进行注释,以确保这些代码的执行速度确实有很大不同。
结果我注意到,当我尝试用鼠标光标移动表单时,第一个代码可以顺利移动并且程序在我的任务管理器中几乎不需要任何处理时间。但是第二个代码使表单每半秒冻结一次(正如预期的那样),而且我的任务管理器中的处理器负载非常明显。
这是什么魔法?...
回答
DateTime.Now通常有~16ms的有限粒度,所以如果你DateTime.Now在短时间内重复访问,返回的大部分值将完全相同。因此,在您的第一个代码片段中,许多循环迭代实际上会将标签的文本设置为已设置的值。如果您检查 .NET源的Control.Text属性,您可以看到,如果您将 设置Text为当前值,它会立即返回,因为它不需要执行任何操作。
另一方面,第二个代码片段中的循环在每次迭代时将标签的文本设置为不同的值,因此标签每次都会运行完整的文本设置代码。因此它比第一个代码片段中的循环做了更多的工作,所以自然需要更长的时间。