我有一个用VB.NET for Framework 4.5编写的WinForms应用程序。
我注意到该应用程序的启动时间异常长(我编写的其他应用程序在启动时还要做更多工作,几乎立即启动,该应用程序需要> 5秒),多次启动后启动时间不会改变,所以我猜在应用程序的第一次启动过程中,不会出现未缓存的CLR代码的情况。

我通过记下启动期间的时间进行了一些测试:

Module modMain
    Public MyLog As System.Text.StringBuilder

    <STAThread>
    Public Sub Main()
        MyLog = New System.Text.StringBuilder

        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        MyLog.AppendLine("Before run: " & Date.Now.ToString & "," & Date.Now.Millisecond.ToString)
        Application.Run(frmMain)
    End Sub
End Module
Sub Main()是应用程序的入口点。它运行frmMain,我可以控制的第一个真正的东西是由设计师生成的Sub InitializeComponent():

<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
    MyLog.AppendLine("Init Start: " & Date.Now.ToString & "," & Date.Now.Millisecond.ToString)
    'All the control initializations
    MyLog.AppendLine("Init End: " & Date.Now.ToString & "," & Date.Now.Millisecond.ToString)
End Sub

最后我到达了Form.Load事件

Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    MyLog.AppendLine("Form_Load Start: " & Date.Now.ToString & "," & Date.Now.Millisecond.ToString)
    '...
    MyLog.AppendLine("Form_Load End: " & Date.Now.ToString & "," & Date.Now.Millisecond.ToString)
End Sub

现在,MyLog的输出如下:

Before run: 15.12.2014 19:56:47,579
Init Start: 15.12.2014 19:56:51,451
Init End: 15.12.2014 19:56:51,521
Form_Load Start: 15.12.2014 19:56:51,544
Form_Load End: 15.12.2014 19:56:51,547

您会看到,主要的停顿发生在Application.Run()Sub InitializeComponent()之间。从其他问题中我知道,已经为GUI线程启动了消息循环,但是我不知道为什么该应用程序比其他应用程序要慢得多。

所以我的问题是:在Application.Run和重新获得对代码的控制权之间到底发生了什么,我可以做些什么来加快速度吗?在那里完成的工作是否与表单上的组件相关?

我已经尝试使用frmMain.ShowDialog()而不是Application.Run(frmMain),但这导致了相同的结果。我正在使用Visual Studio Express,所以很遗憾,我不能使用更深入的性能分析器。

将其标记为C#和VB.NET,因为两种语言的答案都非常受欢迎。

编辑
我做了更多测试,包括在SLaks答案中提出的解决方案。使用NGEN预编译程序集似乎没有明显的效果。所以我想这不是InitializeComponent代码的JIT编译。

但是,我注意到,在其他系统上,即使所涉及的计算机在所有方面都较慢,该程序实际上还是可以立即启动(快10倍以上)。
计算机之间的区别在于操作系统:

Windows 7: Slow start
Windows 8.1: Fast start
Windows Server 2008: Fast start

这些只是更多线索,我真的不知道它是否对回答有用。

编辑2
在启动过程中查看ProcMon,我发现执行挂起在以下几行:

"15:56:29.3547260","Electrochemical Calculator.exe","5972","CreateFile","C:\Users\Jens\Desktop\Electrochemical Calculator Barebone\Electrochemical Calculator\bin\Release\de\Electrochemical Calculator.resources.dll","PATH NOT FOUND","Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a"
"15:56:29.3548019","Electrochemical Calculator.exe","5972","CreateFile","C:\Users\Jens\Desktop\Electrochemical Calculator Barebone\Electrochemical Calculator\bin\Release\de\Electrochemical Calculator.resources\Electrochemical Calculator.resources.dll","PATH NOT FOUND","Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a"
"15:56:29.3548612","Electrochemical Calculator.exe","5972","CreateFile","C:\Users\Jens\Desktop\Electrochemical Calculator Barebone\Electrochemical Calculator\bin\Release\de\Electrochemical Calculator.resources.exe","PATH NOT FOUND","Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a"
"15:56:29.3549519","Electrochemical Calculator.exe","5972","CreateFile","C:\Users\Jens\Desktop\Electrochemical Calculator Barebone\Electrochemical Calculator\bin\Release\de\Electrochemical Calculator.resources\Electrochemical Calculator.resources.exe","PATH NOT FOUND","Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a"
"15:56:32.8796760","Electrochemical Calculator.exe","5972","CreateFile","C:\Windows\Fonts\StaticCache.dat","SUCCESS","Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened"
"15:56:32.8797088","Electrochemical Calculator.exe","5972","QueryStandardInformationFile","C:\Windows\Fonts\StaticCache.dat","SUCCESS","AllocationSize: 9,633,792, EndOfFile: 9,633,792, NumberOfLinks: 1, DeletePending: False, Directory: False"
"15:56:32.8797218","Electrochemical Calculator.exe","5972","ReadFile","C:\Windows\Fonts\StaticCache.dat","SUCCESS","Offset: 0, Length: 60, Priority: Normal"
"15:56:32.8797429","Electrochemical Calculator.exe","5972","CreateFileMapping","C:\Windows\Fonts\StaticCache.dat","FILE LOCKED WITH ONLY READERS","SyncType: SyncTypeCreateSection, PageProtection: "

仅在版本构建中,并且仅当我直接从Windows资源管理器启动程序时,才会进一步出现此问题。从Visual Studio启动时,调试版本会立即启动(0.3秒,而不是5-10秒),而发布版本也会启动。

最佳答案

好了,您消除了所有正常的启动延迟源。它绝对与Application.Run()没有任何关系,直到窗体的InitializeComponent()方法运行完成之后才开始。并且您通过使用Ngen.exe消除了jitting开销。确保区分冷启动延迟和热启动延迟,如果第一次启动程序时延迟很慢,那么这是硬件问题,则需要更快的磁盘。它仅在某些机器上运行缓慢的事实强烈表明存在环境问题。

由InitializeComponent()中运行的代码触发。换句话说,表单上控件的所有构造函数和属性 setter 。通常这只需要很少的时间,但是肯定会有麻烦制造者在周围。您需要寻找一个平凡的控件,尤其是在幕后使用COM(aka ActiveX)的控件。像WebBrowser。类名称以“Ax”开头的任何事物都有很多可能性。这样的控件可以加载许多其他DLL,并且易于引起安全软件的兴趣。

一些调试技巧:

  • 确保您拥有良好的备份,并开始从表单中删除控件,从不重要的控件开始。
  • 在单步执行InitializeComponent()方法时,5秒的延迟足以引起注意。立即告诉您哪个特定的控件和语句导致了延迟。
  • 将调试器切换为非托管模式可以告诉您更多关于其他DLL加载到程序中的信息。在“项目+属性”的“调试”选项卡上,选中“启用本机代码调试”选项。在调试时,请密切注意“输出”窗口,您将看到任何正在加载的非托管DLL的加载通知。这样可以查明导致延迟的特定DLL。
  • 如果可能,请禁用反恶意软件,以便消除由于不适当的DLL扫描而引起的延迟。
  • SysInternals' TcpView实用程序非常适合检测网络延迟。当您看到程序正在与CRL服务器联系时请多加注意,证书吊销列表查询的速度可能会很慢。
  • SysInternals' Process Monitor实用程序非常适合查看由于大多数其他原因引起的延迟。跟踪可能非常大,如果需要另一组跟踪,可以将其保存并发布到文件共享站点上。
  • 关于c# - Application.Run和Form.Load之间会发生什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27491208/

    10-11 11:45