gpt4 book ai didi

c# - Application.Run 和 Form.Load 之间发生了什么?

转载 作者:可可西里 更新时间:2023-11-01 08:21:54 28 4
gpt4 key购买 nike

我有一个用 VB.NET 为 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 answer 中提出的解决方案。使用 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: "

此问题仅在 Release 版本中出现,并且仅在我直接从 Windows 资源管理器启动程序时出现。调试版本立即启动(0.3 秒,相比之下,5-10 秒),从 Visual Studio 启动发布版本也是如此。

最佳答案

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

由在 InitializeComponent() 中运行的代码触发。换句话说,您窗体上控件的所有构造函数和属性 setter 。 通常需要很少的时间,但周围肯定有麻烦制造者。您需要寻找一个重要的控件,尤其是在后台使用 COM(也称为 ActiveX)的控件。就像网络浏览器一样。还有更多的可能性,任何类名以“Ax”开头的东西。此类控件可以加载很多其他 DLL,并且很容易引起安全软件的兴趣。

一些调试技巧:

  • 确保您有一个良好的备份并开始从表单中删除控件,从重要的控件开始。
  • 5 秒的延迟足以在单步执行 InitializeComponent() 方法时引起注意。立即告诉您哪个特定的控件和语句导致了延迟。
  • 将调试器切换到非托管模式可以让您更多地了解哪些其他 DLL 已加载到您的程序中。 Project + Properties,Debug选项卡,勾选“Enable native code debugging”选项。调试时请注意“输出”窗口,您会看到加载任何非托管 DLL 的加载通知。这可以查明导致延迟的特定 DLL。
  • 如果可能,请禁用反恶意软件,这样您就可以消除由于不适当的 DLL 扫描而造成的延迟。
  • SysInternals' TcpView实用程序非常适合检测网络延迟。当您看到您的程序联系 CRL 服务器时要小心,证书吊销列表查询可能很慢。
  • SysInternals' Process Monitor实用程序非常适合查看由于大多数其他原因造成的延迟。痕迹可能非常很大,保存它并将其发布到文件共享网站上(如果您需要另一组眼睛)。

关于c# - Application.Run 和 Form.Load 之间发生了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27491208/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com