Windows Form 控件与 WPF 控件( 第二部分, 性能比较)






4.60/5 (7投票s)
本文主要讨论 Windows 窗体控件和 WPF 控件的性能。它们之间的区别以及内部处理方式。
引言
本文对 Windows 窗体控件和 WPF 控件在系统中的加载方式进行了分析。深入探讨了两种应用程序类型所调用的进程以及消耗的时间。
背景
上一篇文章解释了Windows 和 WPF 应用程序的内存消耗,现在让我们深入探讨与性能相关的方面,并比较涉及的进程。
使用代码
代码与上一篇文章相同,但在此简要总结一下:
为了比较这两种应用程序类型,我们需要创建包含相似控件的应用程序。
在这个例子中,我选择了 TextBox 控件。选择 TextBox 控件的原因是,在
Windows 窗体应用程序中,TextBox
类继承自 System.Windows.Forms.Control (System.Windows.Forms.dll)。
WPF 应用程序中,TextBox
类直接继承自 System.Windows.Controls.Primitives.Control (PresentationFramework.dll)
。
因此,WPF 中的 TextBox 控件不继承自 ContentControl
,从而避免了额外的对象创建开销。
可以说,我们也可以使用 Windows 窗体的 Label
和 TextBlock
,但我们使用 TextBox,因为几乎所有实际应用都会在某个地方使用它。
首先,我们将在 Windows 窗体和 WPF 应用程序中创建 1000 个 TextBox 对象并将其渲染到屏幕上。
让我们创建一个简单的 Windows 窗体应用程序,并将以下代码添加到其中。
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsPerformance
{
public partial class WindowsForm : Form
{
private System.Windows.Forms.TextBox textbox1;
int Iteration = 1000;
public WindowsForm()
{
InitializeComponent();
CreateMultipleTextControls();
}
public void CreateMultipleTextControls()
{
for (int i = 0; i < Iteration; i++)
{
this.textbox1 = new System.Windows.Forms.TextBox();
this.textbox1.Location = new System.Drawing.Point(10, 10);
this.textbox1.Name = "textbox" + i;
this.textbox1.Size = new System.Drawing.Size(150, 150);
this.textbox1.BackColor = Color.Blue;
this.textbox1.TabIndex = 0;
this.textbox1.Text = "textbox";
this.Controls.Add(textbox1);
}
}
}
}
让我们创建一个简单的 WPF 应用程序,并将以下代码添加到其中。
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WPFWinPerformance
{
public partial class MainWindow : Window
{
int Iteration = 1000;
private TextBox textbox1;
public MainWindow()
{
InitializeComponent();
CreateMultipleTextControls();
}
public void CreateMultipleTextControls()
{
for (int i = 0; i < Iteration; i++)
{
this.textbox1 = new TextBox();
this.textbox1.Name = "textbox" + i;
this.textbox1.TabIndex = 0;
this.textbox1.Text = "Text";
this.textbox1.Width = 150;
this.textbox1.Height = 150;
this.textbox1.Background = new SolidColorBrush(Colors.DarkBlue);
this.textbox1.Margin = new Thickness(10, 10, 10, 10);
this.Grid1.Children.Add(textbox1);
}
}
}
}
用于衡量性能的工具是 **Visual Studio 2015 中的 Profiler**。在 profiler 中,结果通过 CPU 使用率(Windows 窗体和 WPF)和应用程序时间线(WPF)等选项捕获。
结果
让我们比较结果,找出应用程序中实际花费时间最多的地方。
Windows 窗体应用程序结果 |
![]() |
WPF 应用程序结果 |
![]() |
以上结果表明,Windows 窗体应用程序加载时间为 5.642 秒,而 WPF 应用程序仅需 4.156 秒,这表明在加载时间方面 WPF 比 Windows 快得多。但我们需要找出原因。在这两个应用程序中,一些非原生代码占用了大约 90% 以上的 CPU 时间。在 Windows 窗体应用程序中,构造函数和 textbox 创建方法占用了大约 11% 的 CPU 时间,而在 WPF 应用程序中,仅占 0.23%。为了获得另一种视图,让我们检查应用程序中的热点路径。
Windows 窗体应用程序结果 |
![]() |
WPF 应用程序结果 |
![]() |
从以上结果可以看出,哪些代码占用了大部分 CPU 时间,在这两种应用程序类型中都是 Application.Run 方法。Application.Run 方法简而言之就是负责创建一个消息循环,用于处理应用程序事件。消息循环调用窗口过程,窗口过程负责处理消息。为了识别这些窗口过程,我们进入进程级别。
Windows 窗体应用程序结果 |
![]() |
![]() |
![]() |
![]() |
以上结果表明,CreateWindow、Comctrl32.dll 等进程占用了大约 70% 的 CPU 时间。Comctrl32.dll(通用控件库)包含提供所有 Windows 应用程序独特外观的控件,因为 Windows 窗体应用程序使用 Windows 操作系统提供的默认 Windows 控件,所以 Comctrl32.dll 进程会被调用是显而易见的。CreateWindow 是创建应用程序窗口的方法。这两个进程在 Windows 窗体应用程序中都是必需的,因为它的框架严重依赖于它们。现在让我们看看 WPF 内部使用了哪些进程。在 Visual Studio 2015 中,有一个用于检查 WPF 应用程序的应用程序时间线功能,这使得内部发生的情况更加清晰。
在这里我们可以观察到,首先进行 XAML 内容的解析,然后是布局创建(包括视觉树的形成),最后是渲染。渲染是使用 Direct 3D 完成的,可以通过调用 wpfgfx.dll 来观察。
总结一下这些发现,可以看出 Windows 窗体对 Comctrl32.dll 等 Windows API 的依赖以及较慢的渲染导致应用程序加载时间比 WPF 增加。这可以解释为 WPF 和 Windows 窗体的渲染模式。
1) WPF 使用保留模式渲染,而 Windows 窗体使用即时模式渲染。
2) WPF 的渲染在组合线程上完成,该线程与 UI 线程不同。
3) WPF 应用程序中使用 GPU,从而加速了渲染过程。
上述测试是在 Windows 10 操作系统和 I3 处理器上进行的,结果可能因旧操作系统而异。
Coding is Simple