我们正在处理WinForm应用程序的慢启动(它是一个大型应用程序,并且有许多控制程序集)。控制组件是DevComponents。应用Ngen来防止jit编译,但加载时间略有下降。
该应用有一个启动画面,但只在应用启动后的12秒内出现。是否有任何方法可以立即显示启动画面?
我们目前的建议是使用启动画面创建一个轻量级应用程序,在单独的进程中运行主应用程序,并在完成主应用程序初始化时关闭轻量级应用程序。
答案 0 :(得分:12)
您永远不会为.NET应用程序提供启动画面以立即显示 。 即使您已经使组件消除了JIT编译时间,您仍然需要等待所有.NET Framework DLL加载到内存中。这是一个非常大的框架,在冷启动时加载需要花费很多时间。你真的无法做到这一点。
微软已尽力减轻痛苦。 WindowsFormsApplicationBase
class(它在Microsoft.VisualBasic
命名空间中定义,但不要让你吓跑;它在C#应用程序中完全可用)提供了一个显示启动画面的内置机制。您所要做的就是将SplashScreen
property设置为适当的形式,其他所有内容都在幕后处理。它已针对最大响应时间进行了大量优化,即使在冷启动情况下也是如此,但它仍然不会即时。
您唯一的另一个选择是在非托管代码中编写小包装器,其唯一目的是尽快抛出启动画面,然后调用.NET应用程序开始启动。当然,打火机越好越好。 C ++是一个选项,但C可能是一个更好的选择。您需要最小化必须链接的外部库的数量,因此像MFC或Qt这样的框架肯定是出局的:您需要直接定位Windows API。
Visual Studio团队在VS 2010中做了类似的事情。他们对流程available on their blog有一个非常有趣的解释:
即使Visual Studio 2010在其主窗口中使用WPF,使用WPF作为启动画面也需要我们等待CLR和WPF初始化才能在屏幕上绘制单个像素。虽然我们在.Net 4.0中对CLR和WPF启动速度进行了一些巨大的改进,但它仍然不能完全匹配原始Win32的性能。因此,选择使用原生C ++代码和Win32作为启动画面。
但我不会在这里花太多时间。由于您通常应该为用户提供打开和关闭启动屏幕的选项,并且大多数用户会选择将其关闭,因此很可能很少有人会首先看到它。任何好的优化分析器都会告诉你它不值得优化。
答案 1 :(得分:5)
对于使用C ++编写并使用本机Windows API的轻量级,可重用的启动画面组件,请参阅Stefan Olson's splash screen。 Cody Gray提出的方法是从单独的非CLR流程开始,然后加载主CLR应用程序。
我必须在上一份工作中实现完全相同的东西,我可以确认方法运行良好 - 用户点击开始菜单中的程序图标和出现的初始屏幕之间的时间只有几毫秒左右感觉'瞬间'。
答案 2 :(得分:1)
我会说你同意你目前的建议。
Winforms应用程序将不会显示,除非它已完全加载到内存中,并且由于需要时间,我建议使用一个加载器应用程序来显示启动并执行主要的巨大应用程序(作为子进程)。
在庞大的应用中,加载后终止父应用。这不会杀死孩子,BTW。
答案 3 :(得分:0)
我过去所做的快速而肮脏的方式是拥有两个应用程序,即主应用程序和启动画面应用程序。主应用程序是正常的,包括所有重量级的DLL,控件等。启动画面应用程序只是一个应用程序和一个Windows窗体,所有不必要的引用DLL从项目中剥离 - 实际上你可以更进一步,使用较轻的.NET框架,如紧凑的.NET框架或早期版本的.NET框架,如1.X或2.0。
您要做的是启动splashscreen应用程序并立即显示单个启动画面。有一个Windows窗体计时器(设置为100毫秒)并启用计时器作为窗体的Load事件的最后一行。当计时器触发时,禁用计时器,然后启动您的实际应用程序。有关如何执行此操作,请参阅this discussion。现在主要应用程序将开始启动。一旦应用程序完成初始化并且可能加载第一个表单,然后让主应用程序终止启动屏幕应用程序。有关杀死应用程序的更多信息here。