c# - 为什么使用 String.Format() 设置标签的文本使用某些 Int32 变量比使用其他 Int32 变量快 20 倍?
问题描述
偶然发现了一个很奇怪的问题,做了一些测试。我是否发现了一些隐藏的框架错误?
(注意:我使用 Visual Studio 2010,我的目标是 .Net Framework 3.5 Client Profile,但我不明白这可能是什么原因)。
我有一个Windows 窗体项目,带有一个窗体、标签和按钮,用于启动计时器组件(在 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
property,您会看到如果您将 设置Text
为当前值,它会立即返回,因为它不需要做任何事情。
另一方面,第二个代码片段中的循环在每次迭代时将标签的文本设置为不同的值,因此标签每次都会运行完整的文本设置代码。因此,它比第一个代码片段中的循环做更多的工作,因此自然需要更长的时间。
推荐阅读
- java - 如何以编程方式在Android中编写部分字符串粗体?
- json - Shopify GraphQL 从服务器获取架构
- python - 抓取网站时,我收到错误“超过 180.0 秒”。为什么?
- python - 跨多个级别的外键填充 django 表列
- c# - WPF ValidationRule 成功消息
- c# - JIT 优化:为什么它很慢以及如何改进它?
- u-sql - 修改全局参数 ADF 管道
- c++ - 使用链表插入数据时程序停止工作
- perl - 具有多个相互依赖的属性的 Perl Moose
- c# - 在运行时动态更改 db.Context 文件中的数据库 DB 首先接近 ASP.net MVC5?